问题
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.
回答1:
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).
来源:https://stackoverflow.com/questions/36296668/colon-in-for-loop-in-c