Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
448 views
in Technique[技术] by (71.8m points)

colon in for loop in C++

In the following code I am trying to edit the contents of an unordered_map:

class A {
public:
    A() {std::cout << "Constructor called, address=" << this << std::endl;val=1;}
    int val;
};

void main(void) {
    std::unordered_map<int,A> um;

    for (int i=0;i<3;i++)
        std::cout << "um[" << i << "]=" << &(um[i]) << ", val=" << um[i].val << std::endl;
    for (auto it : um)
        std::cout << "&it.second=" << &(it.second) << ", val=" << it.second.val << std::endl;

    int index = 1;      
    for (auto um_it : um)
        um_it.second.val = index++;

    for (int i=0;i<3;i++)
        std::cout << "um[" << i << "]=" << &(um[i]) << ", val=" << um[i].val << std::endl;
    for (auto it : um)
        std::cout << "&it.second=" << &(it.second) << ", val=" << it.second.val << std::endl;
}

The output of the above is:

Constructor called, address=0x8dcb2c 
um[0]=0x8dcb2c, val=1 
Constructor called, address=0x8dc7ac 
um[1]=0x8dc7ac, val=1 
Constructor called, address=0x8dc42c 
um[2]=0x8dc42c, val=1 
&it.second=0x7ffc62f24484, val=1 
&it.second=0x7ffc62f24484, val=1 
&it.second=0x7ffc62f24484, val=1 
um[0]=0x8dcb2c, val=1 
um[1]=0x8dc7ac, val=1 
um[2]=0x8dc42c, val=1 
&it.second=0x7ffc62f24484, val=1 
&it.second=0x7ffc62f24484, val=1 
&it.second=0x7ffc62f24484, val=1

When I replace the editing code with:

int index = 1;      
for (auto um_it = um.begin(); um_it != um.end(); ++um_it)
    um_it->second.val = index++;

The output is:

Constructor called, address=0x9d8b2c
um[0]=0x9d8b2c, val=1
Constructor called, address=0x9d87ac
um[1]=0x9d87ac, val=1
Constructor called, address=0x9d842c
um[2]=0x9d842c, val=1
&it.second=0x7fffd2201c34, val=1
&it.second=0x7fffd2201c34, val=1
&it.second=0x7fffd2201c34, val=1
um[0]=0x9d8b2c, val=3
um[1]=0x9d87ac, val=2
um[2]=0x9d842c, val=1
&it.second=0x7fffd2201c34, val=1
&it.second=0x7fffd2201c34, val=2
&it.second=0x7fffd2201c34, val=3

I understand from the results that in the first version the code affects a copy of the objects, but it seems strange. I also expected the copy constructor to be called but it was not. I'd be happy if someone can explain what is going on behind the scenes and what would be the best way to iterate through an unordered_map without making redundant copies.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In the line:

for (auto um_it : um)

um_it is not an iterator. It is a copy of a value in the map. You then modify that copy in the loop body, leaving the map unchanged. This would call the copy-constructor of A for each iteration.

Instead you can operate by reference:

for ( auto& um_item : um )

when um_item refers to an entry in the map. (When using range-based for loop, you cannot access the underlying iterator, you can only access each element or a copy of it).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...