使用对指针的引用作为C ++ 11 range for循环中的序列

时间:2014-12-15 10:43:11

标签: c++ c++11

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

第一个片段:

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

以上代码无法编译,因为&#39;行&#39;是指向int的指针,它不是序列。

第二个片段:

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

此代码编译。如果我正确理解了汽车是如何工作的,那就排好&#39;是指向int的指针。但为什么这个引用可以被视为一个序列而不是常规指针?

3 个答案:

答案 0 :(得分:5)

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

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

foo(row);

这总是会将U推断为row确切类型(如果它是本例中的左值),它会为我们提供数组我们想要的类型。
仅对非参考参数执行的是数组到指针的衰减。

答案 1 :(得分:4)

外部迭代的每个元素都是一个数组。在第一种情况下,auto采用元素值,所以数组指针发生衰减,然后你就不能遍历单个指针。

在第二种情况下,您将获得对数组的引用,您当然可以迭代它。

答案 2 :(得分:0)

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)标准     不需要转换,因此在这样的情况下会被抑制     直接绑定到左值。 - 结束记录]

  

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