为什么在此示例中有“ for(auto&x:v)”而不是“ for(auto x:&v)”?

时间:2019-08-08 09:42:43

标签: c++ pointers reference

我在Bjarne Stroustrup的The C ++编程语言(第4版)中找到了这段代码。

在此示例中,据我所知,我们递增x而不将v的值复制到x中。我的问题是,为什么我们引用x,而不是v?

我试图通过将问题分解并写到纸上来理解问题,简化内存中会发生什么,但我不明白。

void increment()
{
   int v[]={0,1,2,3,4,5,6,7,8,9};

   for(auto& x : v)
      {
        ++x;
      }
}

2 个答案:

答案 0 :(得分:5)

这是一个很好的初学者问题。看一下range-based for loops上的cppreference。由于v是数组类型,因此上面的代码段扩展为

{
    auto && __range = v;

    for (auto __begin = __range, __end = (__range + bound);
        __begin != __end; ++__begin)
    {
        auto& x = *__begin;
        ++x
    }
} 

其中“ bound是数组中元素的数量(如果数组的大小未知或类型不完整,则程序格式不正确)” [来自上面的链接]。

我们可以看到,这种基于范围的for循环背后的机制确保我们在此处对v的左值引用上起作用:auto && __range = v使用带有转发引用的类型推导,正确的事情。

简而言之,在循环中使用auto& x部分时,您可以控制取消引用指向该范围的迭代器(*__begin)时要初始化的内容。例如,使用auto& x可获得范围内元素的引用(可以更改,影响范围),使用const auto& x可获得const限定的元素的引用。范围内的元素(您无法更改)。您可以使用auto x获得每个元素的副本,并使用const获得每个元素的const auto x限定副本,但是后者几乎没有用。

答案 1 :(得分:4)

由于for循环正在更改数组元素,因此您需要引用每个元素以增加它们。

如果您错误地拥有:

for(auto x : v)
{
    ++x;
}

v中的任何内容都不会改变,因为x是数组元素的副本

制作:

for(auto x : &v)
{
    ++x;
}

之所以无法编译,是因为&v是数组 的地址(不是数组中第一个元素的地址,v是),并且在范围表达式中无效。

但是使用:

for(auto& x : v)
{
    ++x;
}

现在将x成为对v中元素的引用,因此可以对其进行更改。