使用对指针的引用作为循环C++11范围内的序列

Using reference to pointer as a sequence in C++11 range for loop

本文关键字:C++11 循环 范围内 指针 引用      更新时间:2023-10-16

以下两个代码片段之间的唯一区别是引用的使用。我理解为什么第一个片段无法编译,并正在寻求帮助以了解第二个片段编译的原因。

第一个片段:

int a[2][3] = {0,1,2,3,4,5};
for (auto row : a)
  for (auto column : row)
    cout << column << endl;

上面的代码无法编译,因为"row"的类型是指向int的指针,int不是一个序列。

第二个片段:

int a[2][3] = {0,1,2,3,4,5};
for (auto &row : a)
  for (auto column : row)
    cout << column << endl;

此代码将编译。如果我正确理解自动的工作原理,"行"是对指向 int 的指针的引用。但是,为什么可以将此引用视为序列而不是常规指针?

类型的推导是通过模板参数推导完成的。

template <typename U>
void foo(U&); // Equivalent to auto&
foo(row);

这将始终推断U确切的row类型(如果在这种情况下它是左值(,这为我们提供了所需的数组类型。
仅对非参考参数执行数组到指针衰减。

外部迭代的每个元素都是一个数组。在第一种情况下,auto按值获取元素,因此会发生数组到指针衰减,然后您无法遍历单个指针。

在第二种情况下,你会得到对数组的引用,你当然可以迭代它。

std::beginstd::end没有指针类型的重载。定义基于范围的 for 循环以使用这些函数。如果要防止发生数组到指针的转换,可以将引用绑定到数组。

§8.5.3

5 对类型">cv1 T1"的引用由表达式初始化 类型">CV2 T2",如下所示:

— 如果引用是左值引用和初始值设定项 表达

— 是一个左值(但不是位字段(,">cv1 T1 " 是 与">CV2 T2"兼容的引用,或

— 具有类类型(即,T2 是类类型(,其中 T1 不是 与T2相关的引用,并且可以隐式转换为 类型为">cv3 T3"的左值,其中">cv1 T1"为 参考兼容">CV3 T3 ">106(此转换 通过枚举适用的转换函数来选择。 (13.3.1.6(并通过重载分辨率选择最佳 (13.3((,

然后将引用绑定到初始值设定项表达式 lvalue 第一种情况和转换的左值结果在 第二种情况(或者,在任一情况下,到适当的基类 对象的子对象(。[ 注:通常的左值到右值 (4.1(, 数组到指针 (4.2( 和函数到指针 (4.3( 标准 转换是不需要的,因此在这样的情况下被禁止 完成与左值的直接绑定。— 尾注 ]

由于第二个项目符号点不适用,因此引用直接绑定到数组,不会发生转换。