C++中循环的冒号

colon in for loop in C++

本文关键字:循环 C++      更新时间:2023-10-16

在下面的代码中,我试图编辑一个无序映射的内容:

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

上述输出为:

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

当我用替换编辑代码时

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

输出为:

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

我从结果中了解到,在第一个版本中,代码会影响对象的副本,但这似乎很奇怪。我还期望调用复制构造函数,但没有。如果有人能解释幕后发生了什么,以及在不制作冗余副本的情况下迭代未定义的映射的最佳方法是什么,我会很高兴。

在行中:

for (auto um_it : um)

um_it不是迭代器。它是映射中某个值的副本。然后修改循环体中的副本,使贴图保持不变。这将为每个迭代调用A的复制构造函数。

相反,您可以参考操作:

for ( auto& um_item : um )

当CCD_ 3引用映射中的条目时。(使用基于范围的for循环时,不能访问底层迭代器,只能访问每个元素或其副本)。