为什么在这个例子中有"for(auto& x : v)"而不是"for(auto x : &v)"?

Why in this example there is "for(auto& x : v)" and not "for(auto x : &v)"?

本文关键字:auto for 为什么      更新时间:2023-10-16

我在Bjarne Stroustrup的The C++ programming language(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;
}
}

这是一个很好的初学者问题。看看 cppPreferred 在基于范围的 for 循环上有什么。由于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 auto x获得每个元素的const限定副本,但后者几乎没有用处。

因为for循环正在更改数组元素,所以您需要对每个元素的引用以递增它们。

如果您错误地拥有:

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

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

制作它:

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

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

但使用:

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

现在使x引用v中的元素,因此可以更改它们。