在插入新密钥时,它会更改现有密钥值的地址吗?

will it change the address of a existed key's value when inserting new keys?

提问人:scirocc 提问时间:5/13/2020 更新时间:5/13/2020 访问量:412

问:

在我的代码中,将在 std::map 中插入或删除,但不会更改现有键的值。 在插入/删除新密钥时,它会更改现有密钥值的地址吗?

int main()
{

    std::map<int,int> m;
    for(int i(0);i<100000;i++){
        m[i];
        std::cout<< &m[0]<<std::endl;
    }

    return 0;
}

结果总是一样的......所以它不会对旧键产生影响? 顺便问一下,unordered_map呢?

C++ 字典 std stdmap 无序

评论

1赞 Damien 5/13/2020
我想它与标准中未定义的实现有关。cpPreference 网站详细说明了这一点,这解释了一般来说,地址不应该改变。Maps are usually implemented as red-black trees
0赞 StefanKssmr 5/13/2020
我不确定键值的地址,但也许它可以帮助您知道在插入/擦除其他元素时,映射中对象的迭代器仍然有效。请看这个答案
0赞 scirocc 5/13/2020
@StefanKssmr THX 为您的提示,这非常丰富!
0赞 scirocc 5/13/2020
@达米安THX男人!

答:

4赞 eerorika 5/13/2020 #1

插入或删除其他元素时,现有元素的地址不会更改。换言之,除非删除该特定元素,否则对元素的引用不会失效。

这适用于所有基于节点的容器,包括关联容器(映射、集合、无序变体、它们的多个变体)和链表。对于基于数组的 deque、vector 或字符串,情况并非如此。

在重新散列的情况下,无序关联容器的迭代器可能会在插入时失效;这不会影响地址。

评论

0赞 scirocc 5/13/2020
由于该规则。如果我启动一个线程进行插入,并在另一个线程中执行 std::map.find(),我可以得到正确的迭代器吗?或者在查找过程中,我只需要添加一个锁,并在查找结束时解锁它,然后我会得到正确的迭代器。
0赞 eerorika 5/13/2020
@scirocc 如果修改容器(即插入),则必须同步访问(即查找)。
2赞 t.niese 5/13/2020 #2

基于 std::map<Key,T,Compare,Allocator>::operator[] 迭代器和引用都不会失效:

[...]返回对映射到与键等效的键的值的引用,如果该键尚不存在,则执行插入。[...]任何迭代器或引用都不会失效

对于 std::unordered_map<Key,T,Hash,KeyEqual,Allocator>::operator[],迭代器可能会无效,但引用不会:

返回对映射到与键等效的键的值的引用,如果该键尚不存在,则执行插入。[...]如果发生插入并导致容器的重新哈希,则所有迭代器都将失效。否则,迭代器不受影响。引用不会失效