for_each& 2D阵列的测距基础

时间:2015-06-03 20:44:45

标签: c++ arrays c++11

我尝试使用for_each和基于范围的for循环打印2D数组。

我的程序是这样的: -

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
  int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
  //for_each (begin(a), end(a), [] (int x) { cout<<x<<" ";}); this code throws error

  for_each (begin(a[0]), end(a[2]), [] (int x) { cout<<x<<" ";});  //this code works well, why ?

  cout<<endl;

  for  (auto &row: a)  // without & for row, error is thrown
  {
     for (auto x:row)  // no & needed for x, why ?
     {
        cout<<x<<" ";
     }
  }
  return 0;
}

为什么我的第一个for_each抛出错误以及为什么行需要&符号?它的类型是什么? row是指针吗?

2 个答案:

答案 0 :(得分:4)

for_each (begin(a), end(a), [] (int x) { cout<<x<<" ";});

begin(a)产生一个int(*)[3](指向大小为[3]的数组的指针),并且取消引用它会产生int(&)[3],而你的lambda表达式需要一个int参数。

for_each (begin(a[0]), end(a[2]), [] (int x) { cout<<x<<" ";});

begin(a[0])会产生一个int*,指向a第一行中的第一个元素,而end(a[2])会产生int*指向一个过去的a <{1}}的最后一行中的最后一个元素,所以一切正常。

现在是基于范围的for部分。

如果从&行中删除for (auto& row : a),则错误实际发生在以下行for(auto x : row)上。这是因为指定了range-based for的方式。与您的用例相关的条款是

  

如果__range是一个数组,那么 begin_expr __range end_expr (__range + __bound),其中__bound是数组中元素的数量(如果数组大小未知或类型不完整,则程序格式错误)

在此,我将引用链接页面的解释部分中提到的标识符。

考虑案例for (auto& row : a)

__range推导为int(&)[3][3](对大小数组的引用[3] [3])。然后将__begin推导为int(*)[3](指向大小数组的指针[3]),因为__range的类型衰减到指向2D数组的第一行的指针。您拥有的 range_expression auto& row,因此row推导为int(&)[3](对大小数组的引用[3])。

接下来,对基于内部范围的for重复相同的过程。在这种情况下,__rangeint(&)[3],并且上面引用的数组子句适用;剩下的类型扣除过程与我上面描述的类似。

__range = int(&)[3]
__begin = int*
x       = int

现在考虑案例for (auto row : a)

__range__begin__end都是相同的。在这种情况下,最重要的区别是 range_expression auto row,这会导致推断出int(*)[3] __begin类型的衰减。这意味着row被推断为int *,并且描述 begin_expr / end_expr 的确定的3个子句中没有一个处理原始指针。这会在嵌套的for循环中导致编译错误。

答案 1 :(得分:3)

a是一个二维数组 - 如果您愿意,可以int[][]

这意味着当您迭代a时,您只迭代第一个数组维度 - a[0]a[2]a[0]仍然是一个数组,它解释了为什么您的第一个for_each可能会产生错误 - 您提供的lambda期望int,但会传递int*

出于同样的原因,在第一个基于范围的基础中需要参考(&amp;符号)。没有&amp;编译器尝试按值复制第一维中的项,但这些是数组本身,并且您无法在C ++中按值复制数组。

第二个基于范围的for不需要引用,因为它正在迭代第二个数组维,它由简单的整数组成。