我试图使用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;
}
Run Code Online (Sandbox Code Playgroud)
为什么我的第一次for_each抛出错误以及为什么&行必须符号?它的类型是什么?是row一个指针?
for_each (begin(a), end(a), [] (int x) { cout<<x<<" ";});
Run Code Online (Sandbox Code Playgroud)
begin(a)产生一个int(*)[3](指向大小为 [3] 的数组的指针),取消引用它会产生一个int(&)[3],而您的 lambda 表达式需要一个int参数。
for_each (begin(a[0]), end(a[2]), [] (int x) { cout<<x<<" ";});
Run Code Online (Sandbox Code Playgroud)
begin(a[0])产生一个int*指向 的第一行中的第一个元素a,并end(a[2])产生int*一个指向 的最后一行中的最后一个元素的指向a,所以一切正常。
现在是基于范围的for部分。
&如果从该行中删除 ,for (auto& row : a)错误实际上会发生在下一行for(auto x : row)。这是因为基于范围的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 是,因此推导为(引用大小为 [3] 的数组)。auto& rowrowint(&)[3]
接下来,对内部基于范围重复相同的过程for。在这种情况下,__rangeisint(&)[3]和我上面引用的数组子句适用;剩下的类型推导过程与我上面描述的类似。
__range = int(&)[3]
__begin = int*
x = int
Run Code Online (Sandbox Code Playgroud)
现在考虑这种情况for (auto row : a):
__range,__begin并且__end都推导出相同的。在这种情况下,关键的区别是range_expression ,它会导致推导的类型auto row衰减。这意味着被推导为,并且描述begin_expr / end_expr的确定的 3 个子句中没有一个处理原始指针。这会导致嵌套循环内出现编译错误。int(*)[3]__beginrowint *for