Last updated:2026-10-12
STL iterator invalidation¶
https://stackoverflow.com/questions/6438086/iterator-invalidation-rules-for-c-containers
Insertion Sequential containers
- vector: all iterators and references before the insertion point are unaffected, unless the new container size exceeds 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 element is at either end of the deque (front or back) (in which case all iterators are invalidated, but references to elements are unaffected) [23.3.3.4/1]
- list: all iterators and references remain unaffected [23.3.5.4/1]
- forward_list: all iterators and references remain unaffected (applies to insert_after) [23.3.4.5/1]
- array: (not applicable)
Associative containers
- [multi]{set,map}: all iterators and references remain unaffected [23.2.4/9]
Unordered associative containers
- unordered_[multi]{set,map}: when a rehash happens, all iterators are invalidated, but references are unaffected [23.2.⅝]. No rehash occurs if the insertion does not cause the container's size to exceed z * B, where z is the maximum load factor and B is the current number of buckets [23.2.5/14]
Container adaptors
- stack: inherited from the underlying container
- queue: inherited from the underlying container
- priority_queue: inherited from the underlying container
Erasure Sequential containers
- vector: every iterator and reference at or after the point of erasure is invalidated [23.3.6.5/3]
- deque: erasing the last element invalidates only iterators and references to the erased element and the past-the-end iterator; erasing the first element invalidates only iterators and references to the erased element; erasing any other element invalidates all iterators and references (including the past-the-end iterator) [23.3.3.4/4]
- list: only iterators and references to the erased element are invalidated [23.3.5.4/3]
- forward_list: only iterators and references to the erased element are invalidated (applies to erase_after) [23.3.4.5/1]
- array: (not applicable)
Associative containers
- [multi]{set,map}: only iterators and references to the erased element are invalidated [23.2.4/9]
Unordered associative containers
- unordered_[multi]{set,map}: only iterators and references to the erased element are invalidated [23.2.5/13]
Container adaptors
- stack: inherited from the underlying container
- queue: inherited from the underlying container
- priority_queue: inherited from the underlying container
Resizing - vector: same as insertion/erasure [23.3.6.5/12] - deque: same as insertion/erasure [23.3.3.3/3] - list: same as insertion/erasure [23.3.5.3/1] - forward_list: same as insertion/erasure [23.3.4.5/25] - array: (not applicable)
Note 1 Unless expressly stated otherwise (either explicitly or by defining a function in terms of other functions), calling a container member function or passing a container as an argument to a library function shall not invalidate iterators to (or change the value of) objects within that container. [23.2.1/11]
Note 2 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] [23.2.1/10]
Note 3 Except for the swap() caveat above, it is not clear whether the "end" iterators are subject to the rules for each container above; in any case, you should assume that they are.
Note 4 vector and all unordered associative containers support reserve(n), which guarantees that no automatic resizing will occur at least until the container size grows to n. Be careful with unordered associative containers, because future proposals will allow setting a minimum load factor, which would allow a rehash to happen on insertion after enough erasures shrink the container below that minimum; so after erasures this guarantee should be considered potentially invalid.
https://en.cppreference.com/w/cpp/container#Iterator_invalidation
for (auto it = c.begin(); it != c.end(); /*inc in loop*/)
{
if (it->shouldErase())
{
it = c.erase(it);
continue;
}
...
++it;
}
auto is_dead = [](auto const& e) { return !(e->is_alive()); };
std::erase_if(m_entities, is_dead);
std::erase_if(m_entity_map, is_dead);
erase_if or remove_if
https://stackoverflow.com/questions/39019806/using-erase-remove-if-idiom
https://kera.name/articles/2011/06/iterator-invalidation-rules-c0x/
Related Topics¶
- STL array source code analysis | C++那些事
- STL string deep dive | C++那些事
- STL string interview questions in depth | C++那些事
- STL deque source code analysis | C++那些事
- STL empty base optimization EBO | C++那些事
- STL hand-written hash table implementation | C++那些事
- STL hashtable hash table | C++那些事
- STL iterator source code analysis | C++那些事
- STL list source code analysis | C++那些事
- STL map and multimap | C++那些事