使用"auto"进行迭代时,"&"符号有什么作用

What does the '&' sign do when using 'auto' for iteration

本文关键字:符号 什么 作用 auto 迭代 使用      更新时间:2023-10-16

最近在C 中使用自动时,我遇到了非常非常奇特的问题,只是...只看以下代码snippet:

我的主要功能:

#include <list>
#include <iostream>
#include <stdio.h>
int main(){ 
    int a = 10, b = 20, c = 30;
    list<int> what;
    what.push_back(a);
    what.push_back(b);
    what.push_back(c);
    read(what);
    return 0;
}

此处的功能已阅读:

void read(const list<int>& con){
    for (auto it : con){
        printf("%pn", &it);
        cout << it << endl;
    }
    return ;
}

这是输出:

0x7fffefff66a4
10
0x7fffefff66a4
20
0x7fffefff66a4
30

那是什么?带有不同内容的相同地址!?

和更奇怪的那就是:

for (auto& it : con){

所有输出立即有意义,地址将通过迭代而改变

所以我的问题是,
为什么'&amp;'在这种情况下签名会更改?

for (auto it : con){

带有不同内容的地址!?

对于具有自动存储持续时间的变量,这是非常典型的。这与C 中的auto无关。。如果您使用了int

,您将获得相同的结果
for (int it : con){

it的寿命(以及循环中的每个自动变量)只是一次迭代。由于上次迭代中it的寿命结束,因此下一个迭代可以重新使用相同的内存,这就是地址相同的原因。


Why does the '&' sign make a change under this circumstance?

因为 T&将a 参考声明为 T。参考变量与非参考(对象变量)不同。引用"指"另一个对象而不是持有诸如对象之类的值。

当您在参考上使用操作员的地址时,结果将是引用对象的地址;不是参考的地址(因为它不是对象,所以甚至可能没有地址)。这就是为什么地址在后一种情况下发生变化的原因。在这种情况下,引用将参考存储在what节点中的int对象(因为con本身是参考,并指转移对象)。


†我在C 中提到,因为在C auto中,实际上是一个表示自动存储类的存储类修饰符。它从未在标准C 中具有这种含义,并且在C中也过时了。这是B语言中的遗迹关键字。

在C 中,auto声明将从上下文推论的类型。

让我们看看:循环语法的扩展版本。

for( auto it: container) {
    ...
}

概念上与

相同
for( auto _it = container.begin(); _it != container.end(); it++) {
    auto it = *_it;
    ...
}

参考表格:

for( auto& it: container)

相同
for( auto _it = container.begin(); _it != container.end(); it++) {
    auto &it = *_it;
    ...
}

因此,在第一种情况下,it是容器中项目的A copy ,在第二种情况下,它是(lvalue)参考,因此,如果您在第二个循环中修改it,它会影响容器中的项目

也可以这样解释地址问题:在 copy 中要在堆栈中使用相同的地址),请三思地址每次都不同,因为参考的地址将产生所引用的对象的地址(在这种情况下为容器中的项目)

请注意,在您的情况下,auto站在int中。所以这是红鲱鱼。考虑

for (int i = 0; i < 10; ++i){
    int j = i;
    cout << (void*)&j << 'n';
}

由于j具有自动存储持续时间,因此很可能每次使用相同的地址创建它 - 但指向不同的值 - j,然后被推开,然后从每次迭代的堆栈中弹出(让我们搁置编译器优化)。这就是您在for (auto it : con){中正在发生的事情。it具有自动存储时间

for (auto& it : con){

it参考对容器con中的int,因此其地址在每个迭代上都会有所不同。