简体   繁体   English

收集更改后,STL迭代器是否保证有效性?

[英]Do STL iterators guarantee validity after collection was changed?

Let's say I have some kind of collection and I obtained an iterator for the beginning of it. 假设我有一些集合,我在它的开头就获得了一个迭代器。 Now let's say I modified the collection. 现在让我们说我修改了这个集合。 Can I still use the iterator safely, regardless of the type of the collection or the iterator? 无论集合的类型还是迭代器,我还能安全地使用迭代器吗?

To avoid confusion, here is the order of operations I talk about: 为避免混淆,这是我谈到的操作顺序:

  1. Get an iterator of the collection. 获取集合的迭代器。
  2. Modify the collection (obviously not an element in it, but the collection itself). 修改集合(显然不是其中的元素,而是集合本身)。
  3. Use the iterator obtained at step 1. Is it stil valid according to STL standard?! 使用在步骤1中获得的迭代器。根据STL标准,它是否有效?!

Depends on the container. 取决于容器。 eg if it's a vector , after modifying the container all iterators can be invalidated. 例如,如果它是一个vector ,则在修改容器之后,所有迭代器都可以无效。 However, if it's a list , the iterators irrelevant to the modified place will remain valid. 但是,如果它是一个list ,则与修改后的位置无关的迭代器将保持有效。

  • A vector's iterators are invalidated when its memory is reallocated. 当重新分配内存时,向量的迭代器将失效。 Additionally, inserting or deleting an element in the middle of a vector invalidates all iterators that point to elements following the insertion or deletion point. 此外,在向量中间插入或删除元素会使指向插入或删除点后面的元素的所有迭代器无效。 It follows that you can prevent a vector's iterators from being invalidated if you use reserve() to preallocate as much memory as the vector will ever use, and if all insertions and deletions are at the vector's end. 因此,如果使用reserve()预分配尽可能多的内存,并且所有插入和删除都在向量的末尾,则可以防止向量的迭代器失效。 [1] [1]

  • The semantics of iterator invalidation for deque is as follows. deque的迭代器失效的语义如下。 Insert (including push_front and push_back ) invalidates all iterators that refer to a deque . Insert (包括push_frontpush_back )使引用deque所有迭代器无效。 Erase in the middle of a deque invalidates all iterators that refer to the deque . deque中间Erase使所有引用deque迭代器无效。 Erase at the beginning or end of a deque (including pop_front and pop_back ) invalidates an iterator only if it points to the erased element. deque的开头或结尾处Erase (包括pop_frontpop_back )只有在指向已擦除元素时才会使迭代器无效。 [2] [2]

  • List s have the important property that insertion and splicing do not invalidate iterators to list elements, and that even removal invalidates only the iterators that point to the elements that are removed. List具有重要的属性,即插入和拼接不会使列表元素的迭代器无效,甚至删除也只会使指向被删除元素的迭代器无效。 [3] [3]

  • Map has the important property that inserting a new element into a map does not invalidate iterators that point to existing elements. Map具有重要的属性,即将新元素插入到map中不会使指向现有元素的迭代器无效。 Erasing an element from a map also does not invalidate any iterators, except, of course, for iterators that actually point to the element that is being erased. 从地图中删除元素也不会使任何迭代器无效,当然,除了实际指向正在被删除的元素的迭代器之外。 [4] (same for set , multiset and multimap ) [4] (同样适用于setmultisetmultimap

That depends on the collection in question. 这取决于有问题的集合。 Just for example, modifying a std::vector (eg, adding an element somewhere) can invalidate all iterators into that vector. 例如,修改std::vector (例如,在某处添加元素)可以使所有迭代器无效到该向量中。 By contrast, with a std::list , iterators remain valid when you add another element to the list. 相反,对于std::list ,当您向列表中添加另一个元素时,迭代器仍然有效。 In some cases, the rules are even more complex (eg, if memory serves, with a std::deque , adding to the beginning or end leaves existing iterators valid, but adding anywhere else can invalidate them -- but my memory is sufficiently poor that you should check before depending on that). 在某些情况下,规则甚至更复杂(例如,如果内存服务,使用std::deque ,添加到开头或结尾使现有迭代器有效,但添加其他任何地方都可能使它们无效 - 但我的记忆力很差你应该检查之前,取决于那个)。

No, iterators are only good while the iterated container is unchanged. 不,迭代器只有在迭代容器不变的情况下才有效。 If a collection is modified, the iterator should be obtained anew. 如果修改了集合,则应重新获取迭代器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM