std::unordered_map insert 仅使迭代器无效,但不会使指向元素节点的引用和指针无效

Har*_*rry 6 c++ unordered-map

有人可以解释为什么插入到std::unordered_map容器中只会使迭代器无效,而不会使引用和指针无效。另外,我无法理解 https://en.cppreference.com/w/cpp/container/unordered_map/insert 中的以下声明的含义

如果插入成功,则在元素保存在节点句柄中时获得的指向该元素的指针和引用将失效,而在提取该元素之前获得的指向该元素的指针和引用将变得有效。

ALX*_*23z 8

插入unordered_map不会使引用无效,因为它不会移动数据,但底层数据结构可能会发生相当大的变化。未指定其具体实现方式的详细信息,并且不同的编译器的执行方式有所不同。例如,MSVC 有一个用于数据存储的链表,我相信还有一个用于查找的向量。并且insert可能导致重新散列,这意味着查找完全改变并且链接列表被显着重新排序 - 但原始数据不会移动。

迭代器引用此底层结构,对其进行任何更改都可能导致迭代器无效。基本上,它们包含比指针和引用更多的信息,并且随后可能会失效。

令人困惑的段落是关于先前提取的inserta - 节点。node_type检查方法unordered_map::extract

https://en.cppreference.com/w/cpp/container/unordered_map/extract

由于某种原因,在提取节点时禁止使用指针/引用。插入后即可再次使用。我不知道为什么会这样。


Ran*_*tep 6

就问题的第二部分而言,它指的是C++17中引入的Node句柄。它是一种仅移动类型,具有底层键和值的直接所有权。它可用于更改元素的密钥而无需重新分配,并可在无需复制或移动的情况下转移元素所有权。

由于允许更改类似const的数据(例如key),因此我个人认为仅在与容器隔离时(即处于节点形式时)才允许进行此类编辑是有意义的;这就是为什么指针和对它的底层数据的引用一旦插入回容器就应该失效。

类似地,由于插入不会引起任何重新分配,因此一旦将节点插入回容器,在提取之前指向数据的指针和引用将再次有效。