Search code examples
c++c++11for-loopreferenceauto

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


recently I've encountered very very peculiar question when using auto in C++, just ... just look at the following code snippet :

my main function:

#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;
}

And here's function read:

void read(const list<int>& con){

    for (auto it : con){
        printf("%p\n", &it);
        cout << it << endl;
    }
    return ;
}

And here's is the output :

0x7fffefff66a4
10
0x7fffefff66a4
20
0x7fffefff66a4
30

What the heck is that? Same address with different content !?

And more strange this is, if I modify the for-loop by adding an '&'
that is:

for (auto& it : con){

All the output makes sense immediately, the addresses would change by iteration

So my question is,
Why does the '&' sign make a change under this circumstance?


Solution

  • for (auto it : con){
    

    Same address with different content !?

    This is very typical for variables with automatic storage duration. This has nothing to do with auto in C++. You would get the same result if you had used int:

    for (int it : con){
    

    The lifetime of it (as well as each automatic variable within the loop) is just a single iteration. Since the lifetime of the it in last iteration was ended, the next iteration can re-use the same memory, and that's why the address is the same.


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

    Because T& declares a reference to type T. Reference variables are different from non-references (object variables). Instead of holding a value such as an object would, a reference instead "refers" to another object.

    When you use the addressof operator on a reference, the result will be the address of the referred object; not the address of the reference (which might not even have an address, since it's not an object). That is why the address changes in the latter case. In this case, the references would refer to the int objects that are stored in the nodes of what (because con itself is a reference, and refers to the passed object).


    † I mention in C++, because in C auto is in fact a storage class modifier that signifies automatic storage class. It has never had that meaning in standard C++, and its use obsolete in C as well. It's a vestigial keyword from the B language.

    In C++, auto declares a type that will be deduced from context.