C++ 容器的迭代器失效规则是什么?
( 注意: 这个问答是期中的一个条目。关于问题本身的元讨论应该发布在开始所有这些的元问题上,而不是在这里。)
C++17 (所有参考资料均来自 CPP17 - n4659的最终工作草案)
序列容器
vector:如果新容量大于旧容量,函数insert, emplace_back,会导致重新分配。重新分配使引用序列中元素的所有引用、指针和迭代器无效。如果没有发生重新分配,则插入点之前的所有迭代器和引用仍然有效。[26.3.11.5/1] 对于函数,重新分配使所有引用序列中元素的引用、指针和迭代器无效。在调用之后发生的插入期间不会发生重新分配,直到插入会使向量的大小大于 的值。[26.3.11.3/6]emplace``push_back reserve``reserve()``capacity()
vector
insert
emplace_back
emplace``push_back
reserve``reserve()``capacity()
deque:在双端队列中间插入会使所有迭代器和对双端队列元素的引用无效。在双端队列的任何一端插入都会使双端队列的所有迭代器无效,但不会影响对双端队列元素的引用的有效性。[26.3.8.4/1]
deque
list:不影响迭代器和引用的有效性。如果抛出异常,则没有任何影响。[26.3.10.4/1]。 此规则涵盖insert, emplace_front, emplace_back, emplace, push_front,函数。push_back
list
emplace_front
emplace
push_front
push_back
forward_list: 的任何重载都insert_after不会影响迭代器和引用的有效性 [26.3.9.5/1]
forward_list
insert_after
array:通常,数组的迭代器在数组的整个生命周期内都不会失效。然而,应该注意的是,在交换期间,迭代器将继续指向同一个数组元素,因此会改变它的值。
array
关联容器
All Associative Containers
无序关联容器
All Unordered Associative Containers: 重新散列使迭代器无效,更改元素之间的顺序,并更改元素出现在哪些桶中,但不会使指针或对元素的引用无效。[26.2.7/9] and成员不应影响对容器元素的引用的有效性,但可能会使容器的所有迭代器无效 。[26.2.7/14] and成员不应影响迭代器的有效性,如果 ,其中是插入操作之前容器中的元素数,是插入的元素数,是容器的桶数,并且是集装箱的最大装载系数。[26.2.7/15]insert``emplace insert``emplace``(N+n) <= z * B``N``n``B``z
All Unordered Associative Containers
insert``emplace
insert``emplace``(N+n) <= z * B``N``n``B``z
All Unordered Associative Containers:在合并操作的情况下(例如,a.merge(a2)),引用被转移元素的迭代器和所有引用的迭代器a都将失效,但剩余元素的迭代器a2将保持有效。(表 91——无序关联容器要求)
a.merge(a2)
a
a2
容器适配器
stack
queue
priority_queue
vector:在擦除点或之后的函数erase和无效迭代器和引用。pop_back[26.3.11.5/3]
erase
pop_back
deque:擦除 a 的最后一个元素的擦除操作deque仅使过去的迭代器和所有迭代器以及对被擦除元素的引用无效。擦除 a 的第一个元素但不擦除最后一个元素的擦除操作deque只会使迭代器和对被擦除元素的引用无效。既不擦除 a 的第一个元素也不擦除最后一个元素的擦除操作deque会使过去的迭代器和所有迭代器以及对deque. [注:pop_front和pop_back是擦除操作。㈥攅第注] [26.3.8.4/4]
pop_front
list:仅使迭代器和对已擦除元素的引用无效。[26.3.10.4/3]。这适用于erase, pop_front, pop_back,clear函数。 remove和remove_if成员函数:擦除列表迭代器引用的列表i中满足以下条件的所有元素:*i == value, pred(*i) != false. 仅使迭代器和对已擦除元素的引用无效 [26.3.10.5/15]。成员函数 - 从迭代器引用的每个连续 unique的相等元素组中擦除除第一个元素之外的所有元素(对于不带参数的唯一版本)或i``[first + 1, last)``*i == *(i-1)``pred(*i, *(i - 1))(对于带有谓词参数的唯一版本)成立。仅使迭代器和对已擦除元素的引用无效。[26.3.10.5/19]
clear
remove
remove_if
i
*i == value
pred(*i) != false
unique
i``[first + 1, last)``*i == *(i-1)``pred(*i, *(i - 1))
forward_list:erase_after应仅使迭代器和对已擦除元素的引用无效。[26.3.9.5/1]。 remove和remove_if成员函数 - 删除列表迭代器 i 引用的列表中的所有元素,其中满足以下条件:*i == value(for remove()),pred(*i)为 true (for remove_if())。仅使迭代器和对已擦除元素的引用无效。[26.3.9.6/12]。 unique成员函数 - 从迭代器 i 引用的每个连续的相等元素组中删除除第一个元素之外的所有元素,范围为 [first + 1, *i == *(i-1)last pred(*i, *(i - 1)))论点)成立。仅使迭代器和对已擦除元素的引用无效。[26.3.9.6/16]
erase_after
remove()
pred(*i)
remove_if()
*i == *(i-1)
pred(*i, *(i - 1))
All Sequence Containers:clear使所有引用 a 元素的引用、指针和迭代器无效,并可能使过去的迭代器无效(表 87 - 序列容器要求)。但是对于forward_list,clear不会使过去的迭代器无效。[26.3.9.5/32]
All Sequence Containers
All Sequence Containers:assign使所有引用容器元素的引用、指针和迭代器无效。对于vectorand deque,也使过去的迭代器无效。(表 87——序列容器要求)
assign
All Associative Containers:erase成员应仅使迭代器和对已擦除元素的引用无效 [26.2.6/9]
All Associative Containers:extract成员只使被移除元素的迭代器失效;指向已删除元素的指针和引用仍然有效 [26.2.6/10]
extract
与迭代器失效有关的一般容器要求:
除非另有规定(明确地或通过根据其他函数定义函数),调用容器成员函数或将容器作为参数传递给库函数不应使该容器内对象的迭代器无效或更改其值. [26.2.1/12]
任何swap()函数都不会使引用被交换容器元素的任何引用、指针或迭代器无效。[ 注意: end() 迭代器不引用任何元素,因此它可能会失效。——第注] [26.2.1/(11.6)]
swap()
作为上述要求的示例:
transform算法:opandbinary_op函数不应使迭代器或子范围无效,或修改范围 [28.6.4/1] 中的元素
transform
op
binary_op
accumulate算法:在 [first, last] 范围内,binary_op既不修改元素也不使迭代器或子范围无效 [29.8.2/1]
accumulate
reduce算法:binary_op 既不能使迭代器或子范围无效,也不能修改范围 [first, last] 中的元素。[29.8.3/5]
reduce
等等…