C++ 迭代器失效规则

C++ 迭代器失效规则,c++,stl,iterator,invalidation,C++,Stl,Iterator,Invalidation,在STL容器类(Vector、Dequeue、list、map、multimap、set、multiset)上操作时,迭代器失效的通常规则是什么。是否有可能对C++的STL程序员在处理容器及其迭代器时必须注意的一些一般规则/准则进行分类和归纳?p> 这些规则是特定于容器的。事实上,这些是决定使用哪个容器的重要标准 例如,插入对象时,std::vector的迭代器可能会失效(取决于插入对象的位置以及是否发生了重新分配),当在迭代器之前删除对象时,迭代器也会失效。std::list没有此问题。插入和

在STL容器类(Vector、Dequeue、list、map、multimap、set、multiset)上操作时,迭代器失效的通常规则是什么。是否有可能对C++的STL程序员在处理容器及其迭代器时必须注意的一些一般规则/准则进行分类和归纳?p> 这些规则是特定于容器的。事实上,这些是决定使用哪个容器的重要标准

例如,插入对象时,
std::vector
的迭代器可能会失效(取决于插入对象的位置以及是否发生了重新分配),当在迭代器之前删除对象时,迭代器也会失效。
std::list
没有此问题。插入和删除对象(迭代器指向的对象除外)不会使迭代器无效


SGI在这方面做得很好。

失效规则的灵感来自于用于实现这些容器的非常基本的数据结构和算法。如果您不打算学习基础知识,那么您需要记住迭代器文档

C++标准以一种方式定义了<代码>迭代器< /代码>的行为,从而可以用简单的C指针实现。它不要求库实际使用指针;它只是使这样做成为可能

基本上,如果操作导致底层存储元素(在
向量中使用的堆数组、在
列表中使用的链表节点或在
映射中使用的树节点或在
集合中使用的树节点)被释放或移动到不同的内存位置,则迭代器无效

向量
通常通过从动态内存(堆)分配数组来实现。为了减少重新分配的数量,阵列总是分配一些空闲空间,即最初未使用的空间。当元素添加到阵列中时,空闲空间将被用完。当所有空闲空间都被占用并且需要插入新元素时,将分配一个更大的新数组。这将导致指向旧数组的所有迭代器失效

同样,当从
向量
中删除元素时,这将导致所有后续元素向前复制。指向移位元素的迭代器仍将引用数组中的相同索引,但该索引现在包含不同的元素。这也是无效的一个例子

对于
list
map
set
,树节点或列表节点在其包含的元素被擦除之前保持有效。注意,指向无效节点的迭代器不能用于任何事情;甚至对于迭代器增量/减量也不行。这是因为在链表或树实现中,迭代器依赖于存储在节点本身中的子指针


为了始终保证正确的操作,与使用简单的数据结构相比,标准的措辞更加严格(矛盾的是,这给了图书馆实施者更多的自由来使用更高级的数据结构)。例如,请参见和。

好的,您可以添加一些。与SGI文档相比,您更喜欢标准文档(这些文档用于较旧的原始STL,而不是标准库)。我确实使用SGI文档进行快速参考,但如果您想确定,那么标准总是有可能发生变化。@Steve:没错,只有我们中的一些人没有可用的标准。请搜索“ISO/IEC 14882:2003(E)”。或者,如果C++编程值26欧元+邮资给你,,-)引用:“一般来说,不改变容器“形状”的简单突变(例如用新值替换数组的第三个元素)不会导致问题。”@Tomalak Geret'kal:这是一个不错的选择!我建议把它加起来作为
c++常见问题解答
条目。@Als:@Tomalak-Geret'kal:啊,对不起,一个小家伙今天忙于这份工作,挣了一点钱;)没注意到你已经注意到了!这很好。注意:虽然数据块中的元素由于push_back()、push_front()、emplace_back()或emplace_front()而不移动,但这些操作仍然会使迭代器无效。