【发布时间】:2012-03-18 07:35:55
【问题描述】:
如果我们有一个 map <int, vector<int> > 是 vectors 在地图的红黑树更改时移动,或者它存储指向 vectors 的指针或类似的东西并且不移动它们(否则使用地图将不会'不再是 O(lg n) 例如如果我们将元素 push_back 到一些 vectors)
【问题讨论】:
如果我们有一个 map <int, vector<int> > 是 vectors 在地图的红黑树更改时移动,或者它存储指向 vectors 的指针或类似的东西并且不移动它们(否则使用地图将不会'不再是 O(lg n) 例如如果我们将元素 push_back 到一些 vectors)
【问题讨论】:
看到这个: std::map, pointer to map key value, is this possible?
第二最佳答案:
第 23.1.2#8 节(关联容器要求):
“插入成员不会影响迭代器和容器引用的有效性,擦除成员只会使迭代器和被擦除元素的引用失效。”
所以 yes 保证存储指向地图元素的数据成员的指针是有效的,除非您删除 那个 元素。
因此,如果保留引用,则无法将数据复制到内存的不同部分。如果是这样的话,我根本看不出执行任何复制的意义......
【讨论】:
std::map 是否允许移动元素?
erase没有这样的要求。
不,向量不会四处移动。树的操作只是重新排列节点之间的指针。它们不会在内存中移动节点或其内容。
【讨论】:
我相信 C++03 不会对内存中数据的稳定性做出任何保证,这将是一个实现细节(实际上,如果不进行测试,您就不能安全地假设这一点) .
注意迭代器到map的保存和实际向量在内存中的位置完全不同。迭代器的有效性在 C++ 规范中明确定义(无论何时有效,何时无效),但树的实际内部行为却没有。
也就是说,任何体面的编译器(对于发布版本/启用优化)都会优化实现,以便在向量在树中移动时不实际复制向量,std::map 的 C++11 实现将使用 move语义来保证这种行为。
你不能假设内部只有指针被移动。
【讨论】:
std::map<K, V> 在标准的所有修订版中都必须是基于节点的容器,即未从映射中删除的节点保留在内存中:迭代器和指向映射元素的指针都不会变为在节点被擦除或地图被破坏之前无效。