C++ 迭代器失效规则

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6438086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:07:58  来源:igfitidea点击:

Iterator invalidation rules

c++c++11iteratorc++17c++-faq

提问by Lightness Races in Orbit

What are the iterator invalidation rules for C++ containers?

C++ 容器的迭代器失效规则是什么?

Preferably in a summary list format.

最好采用摘要列表格式。

(Note: This is meant to be an entry to Stack Overflow's C++ FAQ. If you want to critique the idea of providing an FAQ in this form, then the posting on meta that started all thiswould be the place to do that. Answers to that question are monitored in the C++ chatroom, where the FAQ idea started out in the first place, so your answer is very likely to get read by those who came up with the idea.)

(注意:这是Stack Overflow 的 C++ FAQ 的一个条目。如果你想批评以这种形式提供 FAQ 的想法,那么开始所有这一切的 meta 上的帖子将是这样做的地方。答案该问题在C++ 聊天室中受到监控,FAQ 的想法首先在这里开始,因此您的答案很可能会被提出该想法的人阅读。)

采纳答案by P.W

C++17(All references are from the final working draft of CPP17 - n4659)

C++17(所有参考资料均来自 CPP17 - n4659的最终工作草案)



Insertion

插入

Sequence Containers

序列容器

  • vector: The functions insert, emplace_back, emplace, push_backcause reallocation if the new size is greater than the old capacity. Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence. If no reallocation happens, all the iterators and references before the insertion point remain valid. [26.3.11.5/1]
    With respect to the reservefunction, reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence. No reallocation shall take place during insertions that happen after a call to reserve()until the time when an insertion would make the size of the vector greater than the value of capacity(). [26.3.11.3/6]

  • deque: An insertion in the middle of the deque invalidates all the iterators and references to elements of the deque. An insertion at either end of the deque invalidates all the iterators to the deque, but has no effect on the validity of references to elements of the deque. [26.3.8.4/1]

  • list: Does not affect the validity of iterators and references. If an exception is thrown there are no effects. [26.3.10.4/1].
    The insert, emplace_front, emplace_back, emplace, push_front, push_backfunctions are covered under this rule.

  • forward_list: None of the overloads of insert_aftershall affect the validity of iterators and references [26.3.9.5/1]

  • array: As a rule, iterators to an array are never invalidated throughout the lifetime of the array. One should take note, however, that during swap, the iterator will continue to point to the same array element, and will thus change its value.

  • vector:如果新容量大于旧容量,函数insert, emplace_back,会导致重新分配。重新分配使指向序列中元素的所有引用、指针和迭代器无效。如果没有发生重新分配,插入点之前的所有迭代器和引用仍然有效。[26.3.11.5/1] 对于函数,重新分配会使所有引用序列中元素的引用、指针和迭代器无效。在调用之后的插入过程中不会发生重新分配,直到插入会使向量的大小大于 的值。[26.3.11.3/6] emplacepush_back
    reservereserve()capacity()

  • deque:在双端队列中间插入会使所有迭代器和对双端队列元素的引用无效。在双端队列的任一端插入会使双端队列的所有迭代器无效,但对双端队列元素引用的有效性没有影响。[26.3.8.4/1]

  • list: 不影响迭代器和引用的有效性。如果抛出异常,则没有任何影响。[26.3.10.4/1]。
    insertemplace_frontemplace_backemplacepush_frontpush_back功能是在本规则覆盖。

  • forward_list: 的重载insert_after不应影响迭代器和引用的有效性 [26.3.9.5/1]

  • array作为一项规则,数组的迭代器在数组的整个生命周期中永远不会失效。然而,应该注意的是,在交换期间,迭代器将继续指向同一个数组元素,从而改变其值。

Associative Containers

关联容器

  • All Associative Containers: The insertand emplacemembers shall not affect the validity of iterators and references to the container [26.2.6/9]
  • All Associative Containers:insertemplace成员不应影响迭代器的有效性和对容器的引用 [26.2.6/9]

Unordered Associative Containers

无序关联容器

  • All Unordered Associative Containers: Rehashing invalidates iterators, changes ordering between elements, and changes which buckets elements appear in, but does not invalidate pointers or references to elements. [26.2.7/9]
    The insertand emplacemembers shall not affect the validity of references to container elements, but may invalidate all iterators to the container. [26.2.7/14]
    The insertand emplacemembers shall not affect the validity of iterators if (N+n) <= z * B, where Nis the number of elements in the container prior to the insert operation, nis the number of elements inserted, Bis the container's bucket count, and zis the container's maximum load factor. [26.2.7/15]

  • All Unordered Associative Containers: In case of a merge operation (e.g., a.merge(a2)), iterators referring to the transferred elements and all iterators referring to awill be invalidated, but iterators to elements remaining in a2will remain valid. (Table 91 — Unordered associative container requirements)

  • All Unordered Associative Containers:重新散列使迭代器无效,更改元素之间的顺序,并更改元素出现在哪些桶中,但不会使元素的指针或引用无效。[26.2.7 / 9]
    insertemplace成员不应影响到容器元素的引用的有效性,但可能违反所有迭代器在容器上。[26.2.7 / 14]
    insertemplace成员不应影响迭代器的有效性,如果(N+n) <= z * B,在这里N是在之前的插入操作的容器中的元素的数量,n是插入的元素的数量,B是容器的桶计数,以及z是集装箱的最大装载系数。[26.2.7/15]

  • All Unordered Associative Containers: 在合并操作的情况下(例如,a.merge(a2)),引用传输元素的迭代器和引用的所有迭代器a都将失效,但指向剩余元素的迭代器a2将保持有效。(表 91 — 无序关联容器要求)

Container Adaptors

容器适配器

  • stack: inherited from underlying container
  • queue: inherited from underlying container
  • priority_queue: inherited from underlying container
  • stack: 从底层容器继承
  • queue: 从底层容器继承
  • priority_queue: 从底层容器继承


Erasure

擦除

Sequence Containers

序列容器

  • vector: The functions eraseand pop_backinvalidate iterators and references at or after the point of the erase. [26.3.11.5/3]

  • deque: An erase operation that erases the last element of a dequeinvalidates only the past-the-end iterator and all iterators and references to the erased elements. An erase operation that erases the first element of a dequebut not the last element invalidates only iterators and references to the erased elements. An erase operation that erases neither the first element nor the last element of a dequeinvalidates the past-the-end iterator and all iterators and references to all the elements of the deque. [ Note: pop_frontand pop_backare erase operations. —end note ] [26.3.8.4/4]

  • list: Invalidates only the iterators and references to the erased elements. [26.3.10.4/3]. This applies to erase, pop_front, pop_back, clearfunctions.
    removeand remove_ifmember functions: Erases all the elements in the list referred by a list iterator ifor which the following conditions hold: *i == value, pred(*i) != false. Invalidates only the iterators and references to the erased elements [26.3.10.5/15].
    uniquemember function - Erases all but the first element from every consecutive group of equal elements referred to by the iterator iin the range [first + 1, last)for which *i == *(i-1)(for the version of unique with no arguments) or pred(*i, *(i - 1))(for the version of unique with a predicate argument) holds. Invalidates only the iterators and references to the erased elements. [26.3.10.5/19]

  • forward_list: erase_aftershall invalidate only iterators and references to the erased elements. [26.3.9.5/1].
    removeand remove_ifmember functions - Erases all the elements in the list referred by a list iterator i for which the following conditions hold: *i == value(for remove()), pred(*i)is true (for remove_if()). Invalidates only the iterators and references to the erased elements. [26.3.9.6/12].
    uniquemember function - Erases all but the first element from every consecutive group of equal elements referred to by the iterator i in the range [first + 1, last) for which *i == *(i-1)(for the version with no arguments) or pred(*i, *(i - 1))(for the version with a predicate argument) holds. Invalidates only the iterators and references to the erased elements. [26.3.9.6/16]

  • All Sequence Containers: clearinvalidates all references, pointers, and iterators referring to the elements of a and may invalidate the past-the-end iterator (Table 87 — Sequence container requirements). But for forward_list, cleardoes not invalidate past-the-end iterators. [26.3.9.5/32]

  • All Sequence Containers: assigninvalidates all references, pointers and iterators referring to the elements of the container. For vectorand deque, also invalidates the past-the-end iterator. (Table 87 — Sequence container requirements)

  • vector:在擦除点或之后的函数erasepop_back无效迭代器和引用。[26.3.11.5/3]

  • deque:擦除 a 的最后一个元素的擦除操作deque只会使最后的迭代器和所有迭代器以及对被擦除元素的引用无效。擦除 a 的第一个元素deque而不是最后一个元素的擦除操作只会使迭代器和对被擦除元素的引用无效。既不擦除 a 的第一个元素也不擦除最后一个元素的擦除操作deque会使尾后迭代器和所有迭代器以及对 的所有元素的引用无效deque。[注:pop_frontpop_back是擦除操作。——尾注] [26.3.8.4/4]

  • list:仅使迭代器和对已擦除元素的引用无效。[26.3.10.4/3]。这适用于erase, pop_front, pop_back,clear函数。
    removeremove_if成员函数:擦除i满足以下条件的列表迭代器所引用的列表中的所有元素:*i == value, pred(*i) != false。仅使迭代器和对已擦除元素的引用无效 [26.3.10.5/15]。
    unique成员函数-删除所有但第一元件从等于元件的每个连续组称为由迭代器i在范围[first + 1, last)为其中*i == *(i-1)(对于版本的唯一没有参数)或pred(*i, *(i - 1))(对于带有谓词参数的 unique 版本)成立。仅使迭代器和对已擦除元素的引用无效。[26.3.10.5/19]

  • forward_list:erase_after应仅使迭代器和对已擦除元素的引用无效。[26.3.9.5/1]。
    removeremove_if成员函数 - 擦除列表迭代器 i 引用的列表中的所有元素,其中满足以下条件:*i == value(for remove()),pred(*i)为真(for remove_if())。仅使迭代器和对已擦除元素的引用无效。[26.3.9.6/12]。
    unique成员函数 - 从迭代器 i 引用的每个连续相等元素组中删除除第一个元素外的所有元素,范围为 [first + 1, last) for which *i == *(i-1)(对于没有参数的版本) or pred(*i, *(i - 1))(对于有谓词的版本论证)成立。仅使迭代器和对已擦除元素的引用无效。[26.3.9.6/16]

  • All Sequence Containersclear使所有引用 a 元素的引用、指针和迭代器无效,并可能使尾后迭代器无效(表 87 — 序列容器要求)。但是对于forward_list,clear不会使过去的迭代器无效。[26.3.9.5/32]

  • All Sequence Containers:assign使所有引用容器元素的引用、指针和迭代器失效。对于vectorand deque,也会使过去的迭代器无效。(表 87 — 序列容器要求)

Associative Containers

关联容器

  • All Associative Containers: The erasemembers shall invalidate only iterators and references to the erased elements [26.2.6/9]

  • All Associative Containers: The extractmembers invalidate only iterators to the removed element; pointers and references to the removed element remain valid [26.2.6/10]

  • All Associative Containerserase成员应仅使迭代器和对已擦除元素的引用无效 [26.2.6/9]

  • All Associative Containersextract成员仅使删除元素的迭代器无效;指向已删除元素的指针和引用仍然有效 [26.2.6/10]

Container Adaptors

容器适配器

  • stack: inherited from underlying container
  • queue: inherited from underlying container
  • priority_queue: inherited from underlying container
  • stack: 从底层容器继承
  • queue: 从底层容器继承
  • priority_queue: 从底层容器继承


General container requirements relating to iterator invalidation:

与迭代器失效相关的一般容器要求:

  • Unless otherwise specified (either explicitly or by defining a function in terms of other functions), invoking a container member function or passing a container as an argument to a library function shall not invalidate iterators to, or change the values of, objects within that container. [26.2.1/12]

  • no swap()function invalidates any references, pointers, or iterators referring to the elements of the containers being swapped. [ Note: The end() iterator does not refer to any element, so it may be invalidated. —end note ] [26.2.1/(11.6)]

  • 除非另有说明(明确地或通过根据其他函数定义函数),调用容器成员函数或将容器作为参数传递给库函数不应使该容器内的对象的迭代器无效或更改其值. [26.2.1/12]

  • 没有swap()函数使任何引用、指针或迭代器无效,这些引用、指针或迭代器引用了被交换的容器的元素。[ 注意:end() 迭代器不引用任何元素,因此它可能会失效。——尾注] [26.2.1/(11.6)]

As examples of the above requirements:

作为上述要求的示例:

  • transformalgorithm: The opand binary_opfunctions shall not invalidate iterators or subranges, or modify elements in the ranges [28.6.4/1]

  • accumulatealgorithm: In the range [first, last], binary_opshall neither modify elements nor invalidate iterators or subranges [29.8.2/1]

  • reducealgorithm: binary_op shall neither invalidate iterators or subranges, nor modify elements in the range [first, last]. [29.8.3/5]

  • transform算法:opbinary_op函数不应使迭代器或子范围无效,或修改范围内的元素 [28.6.4/1]

  • accumulate算法:在 [first, last] 范围内,binary_op不得修改元素或使迭代器或子范围无效 [29.8.2/1]

  • reduce算法: binary_op 不应使迭代器或子范围无效,也不应修改范围 [first, last] 中的元素。[29.8.3/5]

and so on...

等等...

回答by Lightness Races in Orbit

C++03(Source: Iterator Invalidation Rules (C++03))

C++03(来源:迭代器失效规则(C++03)



Insertion

插入

Sequence containers

序列容器

  • vector: all iterators and references before the point of insertion are unaffected, unless the new container size is greater than the previous capacity (in which case all iterators and references are invalidated) [23.2.4.3/1]
  • deque: all iterators and references are invalidated, unless the inserted member is at an end (front or back) of the deque (in which case all iterators are invalidated, but references to elements are unaffected) [23.2.1.3/1]
  • list: all iterators and references unaffected [23.2.2.3/1]
  • vector: 插入点之前的所有迭代器和引用不受影响,除非新容器大小大于之前的容量(在这种情况下所有迭代器和引用都无效)[23.2.4.3/1]
  • deque:所有迭代器和引用都无效,除非插入的成员位于双端队列的末尾(前面或后面)(在这种情况下,所有迭代器都无效,但对元素的引用不受影响)[23.2.1.3/1]
  • list:所有迭代器和引用不受影响 [23.2.2.3/1]

Associative containers

关联容器

  • [multi]{set,map}: all iterators and references unaffected [23.1.2/8]
  • [multi]{set,map}:所有迭代器和引用不受影响 [23.1.2/8]

Container adaptors

容器适配器

  • stack: inherited from underlying container
  • queue: inherited from underlying container
  • priority_queue: inherited from underlying container
  • stack: 从底层容器继承
  • queue: 从底层容器继承
  • priority_queue: 从底层容器继承


Erasure

擦除

Sequence containers

序列容器

  • vector: every iterator and reference after the point of erase is invalidated [23.2.4.3/3]
  • deque: all iterators and references are invalidated, unless the erased members are at an end (front or back) of the deque (in which case only iterators and references to the erased members are invalidated) [23.2.1.3/4]
  • list: only the iterators and references to the erased element is invalidated [23.2.2.3/3]
  • vector:擦除点之后的每个迭代器和引用都无效 [23.2.4.3/3]
  • deque:所有迭代器和引用都无效,除非被擦除的成员位于双端队列的末尾(前面或后面)(在这种情况下,只有迭代器和对被擦除成员的引用无效)[23.2.1.3/4]
  • list:只有迭代器和对被擦除元素的引用无效 [23.2.2.3/3]

Associative containers

关联容器

  • [multi]{set,map}: only iterators and references to the erased elements are invalidated [23.1.2/8]
  • [multi]{set,map}: 只有迭代器和对被擦除元素的引用无效 [23.1.2/8]

Container adaptors

容器适配器

  • stack: inherited from underlying container
  • queue: inherited from underlying container
  • priority_queue: inherited from underlying container
  • stack: 从底层容器继承
  • queue: 从底层容器继承
  • priority_queue: 从底层容器继承


Resizing

调整大小

  • vector: as per insert/erase [23.2.4.2/6]
  • deque: as per insert/erase [23.2.1.2/1]
  • list: as per insert/erase [23.2.2.2/1]
  • vector:根据插入/擦除 [23.2.4.2/6]
  • deque:根据插入/擦除 [23.2.1.2/1]
  • list:根据插入/擦除 [23.2.2.2/1]


Note 1

注 1

Unless otherwise specified(either explicitly or by defining a function in terms of other functions), invoking a container member function or passing a container as an argument to a library function shall not invalidate iteratorsto, or change the values of, objects within that container. [23.1/11]

除非另有说明(明确地或通过根据其他函数定义函数),调用容器成员函数或将容器作为参数传递给库函数不应使该容器内的对象的迭代器无效或更改其值. [23.1/11]

Note 2

笔记2

It's not clear in C++2003 whether "end" iterators are subject to the above rules; you should assume, anyway, that they are (as this is the case in practice).

在 C++2003 中不清楚“结束”迭代器是否受上述规则的约束;无论如何,您应该假设它们是(因为在实践中就是这种情况)。

Note 3

注 3

The rules for invalidation of pointers are the sames as the rules for invalidation of references.

指针失效规则与引用失效规则相同。

回答by Lightness Races in Orbit

C++11(Source: Iterator Invalidation Rules (C++0x))

C++11(来源:迭代器失效规则(C++0x)



Insertion

插入

Sequence containers

序列容器

  • vector: all iterators and references before the point of insertion are unaffected, unless the new container size is greater than the previous capacity (in which case all iterators and references are invalidated) [23.3.6.5/1]
  • deque: all iterators and references are invalidated, unless the inserted member is at an end (front or back) of the deque (in which case all iterators are invalidated, but references to elements are unaffected) [23.3.3.4/1]
  • list: all iterators and references unaffected [23.3.5.4/1]
  • forward_list: all iterators and references unaffected (applies to insert_after)[23.3.4.5/1]
  • array: (n/a)
  • vector: 插入点之前的所有迭代器和引用不受影响,除非新容器大小大于之前的容量(在这种情况下所有迭代器和引用都无效)[23.3.6.5/1]
  • deque:所有迭代器和引用都无效,除非插入的成员位于双端队列的末尾(前面或后面)(在这种情况下,所有迭代器都无效,但对元素的引用不受影响)[23.3.3.4/1]
  • list:所有迭代器和引用不受影响 [23.3.5.4/1]
  • forward_list:所有迭代器和引用不受影响(适用于insert_after[23.3.4.5/1]
  • array:(不适用)

Associative containers

关联容器

  • [multi]{set,map}: all iterators and references unaffected [23.2.4/9]
  • [multi]{set,map}:所有迭代器和引用不受影响 [23.2.4/9]

Unsorted associative containers

未分类的关联容器

  • unordered_[multi]{set,map}: all iterators invalidated when rehashing occurs, but references unaffected [23.2.5/8]. Rehashing does not occur if the insertion does not cause the container's size to exceed z * Bwhere zis the maximum load factor and Bthe current number of buckets. [23.2.5/14]
  • unordered_[multi]{set,map}: 所有迭代器在重新散列时失效,但引用不受影响 [23.2.5/8]。重散列如果插入不会导致超过容器的大小也不会发生z * B,其中z为最大负载因数和B桶的当前数目。[23.2.5/14]

Container adaptors

容器适配器

  • stack: inherited from underlying container
  • queue: inherited from underlying container
  • priority_queue: inherited from underlying container
  • stack: 从底层容器继承
  • queue: 从底层容器继承
  • priority_queue: 从底层容器继承


Erasure

擦除

Sequence containers

序列容器

  • vector: every iterator and reference at or after the point of erase is invalidated [23.3.6.5/3]
  • deque: erasing the last element invalidates only iterators and references to the erased elements and the past-the-end iterator; erasing the first element invalidates only iterators and references to the erased elements; erasing any other elements invalidates all iterators and references (including the past-the-end iterator) [23.3.3.4/4]
  • list: only the iterators and references to the erased element is invalidated [23.3.5.4/3]
  • forward_list: only the iterators and references to the erased element is invalidated (applies to erase_after)[23.3.4.5/1]
  • array: (n/a)
  • vector:擦除点或之后的每个迭代器和引用都无效 [23.3.6.5/3]
  • deque:擦除最后一个元素只会使迭代器和对被擦除元素的引用和最后的迭代器无效;擦除第一个元素只会使迭代器和对被擦除元素的引用无效;擦除任何其他元素会使所有迭代器和引用无效(包括过去的迭代器)[23.3.3.4/4]
  • list:只有迭代器和对被擦除元素的引用无效 [23.3.5.4/3]
  • forward_list:只有迭代器和对被擦除元素的引用无效(适用于erase_after[23.3.4.5/1]
  • array:(不适用)

Associative containers

关联容器

  • [multi]{set,map}: only iterators and references to the erased elements are invalidated [23.2.4/9]
  • [multi]{set,map}: 只有迭代器和对被擦除元素的引用无效 [23.2.4/9]

Unordered associative containers

无序关联容器

  • unordered_[multi]{set,map}: only iterators and references to the erased elements are invalidated [23.2.5/13]
  • unordered_[multi]{set,map}: 只有迭代器和对被擦除元素的引用无效 [23.2.5/13]

Container adaptors

容器适配器

  • stack: inherited from underlying container
  • queue: inherited from underlying container
  • priority_queue: inherited from underlying container
  • stack: 从底层容器继承
  • queue: 从底层容器继承
  • priority_queue: 从底层容器继承


Resizing

调整大小

  • vector: as per insert/erase [23.3.6.5/12]
  • deque: as per insert/erase [23.3.3.3/3]
  • list: as per insert/erase [23.3.5.3/1]
  • forward_list: as per insert/erase [23.3.4.5/25]
  • array: (n/a)
  • vector:根据插入/擦除 [23.3.6.5/12]
  • deque:根据插入/擦除 [23.3.3.3/3]
  • list:根据插入/擦除 [23.3.5.3/1]
  • forward_list:根据插入/擦除 [23.3.4.5/25]
  • array:(不适用)


Note 1

注 1

Unless otherwise specified(either explicitly or by defining a function in terms of other functions), invoking a container member function or passing a container as an argument to a library function shall not invalidate iteratorsto, or change the values of, objects within that container. [23.2.1/11]

除非另有说明(明确地或通过根据其他函数定义函数),调用容器成员函数或将容器作为参数传递给库函数不应使该容器内的对象的迭代器无效或更改其值. [23.2.1/11]

Note 2

笔记2

no swap() function invalidates any references, pointers, or iteratorsreferring to the elements of the containers being swapped. [ Note: The end() iteratordoes not refer to any element, so it may be invalidated. —end note ] [23.2.1/10]

没有 swap() 函数使任何引用、指针或迭代器无效,这些引用、指针或迭代器引用了被交换的容器的元素。[注意:end() 迭代器不引用任何元素,因此它可能会失效。——尾注] [23.2.1/10]

Note 3

注 3

Other than the above caveat regarding swap(), it's not clear whether "end" iterators are subject to the above listed per-container rules; you should assume, anyway, that they are.

除了上述关于 的警告之外swap()尚不清楚“结束”迭代器是否受上面列出的每个容器规则的约束;无论如何,你应该假设它们是。

Note 4

注 4

vectorand all unordered associative containerssupport reserve(n)which guarantees that no automatic resizing will occur at least until the size of the container grows to n. Caution should be taken with unordered associative containersbecause a future proposal will allow the specification of a minimum load factor, which would allow rehashing to occur on insertafter enough eraseoperations reduce the container size below the minimum; the guarantee should be considered potentially void after an erase.

vector并且所有无序关联容器都支持reserve(n)这保证至少在容器大小增长到 之前不会发生自动调整大小n。对无序关联容器应谨慎,因为未来的提案将允许指定最小负载因子,这将允许insert在足够的erase操作将容器大小减小到最小值以下后进行重新散列;在 之后,该保证应被视为可能无效erase

回答by AnT

It is probably worth adding that an insert iterator of any kind (std::back_insert_iterator, std::front_insert_iterator, std::insert_iterator) is guaranteed to remain valid as long as all insertions are performed through this iterator and no other independent iterator-invalidating event occurs.

可能值得补充的是,只要所有插入都通过此迭代器执行并且没有其他独立的迭代器无效事件发生,则任何类型 ( std::back_insert_iterator, std::front_insert_iterator, std::insert_iterator)的插入迭代器都可以保证保持有效。

For example, when you are performing a series of insertion operations into a std::vectorby using std::insert_iteratorit is quite possible that these insertions will trigger vector reallocation, which will invalidate all iterators that "point" into that vector. However, the insert iterator in question is guaranteed to remain valid, i.e. you can safely continue the sequence of insertions. There's no need to worry about triggering vector reallocation at all.

例如,当您std::vector通过使用对 a 执行一系列插入操作时std::insert_iterator,这些插入很可能会触发向量重新分配,这将使“指向”该向量的所有迭代器无效。但是,有问题的插入迭代器保证保持有效,即您可以安全地继续插入序列。根本不需要担心触发向量重新分配。

This, again, applies only to insertions performed through the insert iterator itself. If iterator-invalidating event is triggered by some independent action on the container, then the insert iterator becomes invalidated as well in accordance with the general rules.

同样,这仅适用于通过插入迭代器本身执行的插入。如果 iterator-invalidating 事件是由容器上的某个独立操作触发的,那么插入迭代器也会按照一般规则失效。

For example, this code

例如,这段代码

std::vector<int> v(10);
std::vector<int>::iterator it = v.begin() + 5;
std::insert_iterator<std::vector<int> > it_ins(v, it);

for (unsigned n = 20; n > 0; --n)
  *it_ins++ = rand();

is guaranteed to perform a valid sequence of insertions into the vector, even if the vector "decides" to reallocate somewhere in the middle of this process. Iterator itwill obviously become invalid, but it_inswill continue to remain valid.

保证对向量执行有效的插入序列,即使向量“决定”在此过程中间的某个地方重新分配。迭代器it显然会失效,但it_ins会继续保持有效。

回答by neverhoodboy

Since this question draws so many votes and kind of becomes an FAQ, I guess it would be better to write a separate answer to mention one significant difference between C++03 and C++11 regarding the impact of std::vector's insertion operation on the validity of iterators and references with respect to reserve()and capacity(), which the most upvoted answer failed to notice.

由于这个问题吸引了如此多的选票并且成为了一个常见问题解答,我想最好写一个单独的答案来提及 C++03 和 C++11 之间关于std::vector插入操作对 的影响的一个显着差异迭代器和引用相对的有效性reserve()capacity(),其中最upvoted答案没有注意到。

C++ 03:

C++ 03:

Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence. It is guaranteed that no reallocation takes place during insertions that happen after a call to reserve() until the time when an insertion would make the size of the vector greater than the size specified in the most recent call to reserve().

重新分配使指向序列中元素的所有引用、指针和迭代器无效。保证在调用 reserve() 之后发生的插入过程中不会发生重新分配,直到插入使向量的大小大于最近一次调用 reserve() 中指定的大小为止。

C++11:

C++11:

Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence. It is guaranteed that no reallocation takes place during insertions that happen after a call to reserve() until the time when an insertion would make the size of the vector greater than the value of capacity().

重新分配使指向序列中元素的所有引用、指针和迭代器无效。保证在调用 Reserve() 之后发生的插入过程中不会发生重新分配,直到插入会使向量的大小大于 capacity() 的值

So in C++03, it is not "unless the new container size is greater than the previous capacity (in which case all iterators and references are invalidated)" as mentioned in the other answer, instead, it should be "greater than the size specified in the most recent call to reserve()". This is one thing that C++03 differs from C++11. In C++03, once an insert()causes the size of the vector to reach the value specified in the previous reserve()call (which could well be smaller than the current capacity()since a reserve()could result a bigger capacity()than asked for), any subsequent insert()could cause reallocation and invalidate all the iterators and references. In C++11, this won't happen and you can always trust capacity()to know with certainty that the next reallocation won't take place before the size overpasses capacity().

因此,在 C++03 中,它不是unless the new container size is greater than the previous capacity (in which case all iterators and references are invalidated)另一个答案中提到的“ ”,而应该是“ greater than the size specified in the most recent call to reserve()”。这是 C++03 与 C++11 不同的一件事。在 C++03 中,一旦 ainsert()导致向量的大小达到前一次reserve()调用中指定的值(这很可能小于当前值,capacity()因为 areserve()可能导致capacity()大于要求的值),任何后续insert()都可能导致重新分配和无效所有的迭代器和引用。在 C++11 中,这不会发生,您总是可以确信capacity()知道在大小超过之前不会发生下一次重新分配capacity()

In conclusion, if you are working with a C++03 vector and you want to make sure a reallocation won't happen when you perform insertion, it's the value of the argument you previously passed to reserve()that you should check the size against, not the return value of a call to capacity(), otherwise you may get yourself surprised at a "premature" reallocation.

总之,如果您正在使用 C++03 向量,并且想要确保在执行插入时不会发生重新分配,那么reserve()您应该检查之前传递给的参数的值,而不是调用的返回值capacity(),否则您可能会对“过早的”重新分配感到惊讶。

回答by DarioP

Here is a nice summary table from cppreference.com:

这是来自cppreference.com 的一个不错的汇总表:

enter image description here

在此处输入图片说明

Here, insertionrefers to any method which adds one or more elements to the container and erasurerefers to any method which removes one or more elements from the container.

这里,插入是指将一个或多个元素添加到容器中的任何方法,而擦除是指从容器中删除一个或多个元素的任何方法。