Middle+
How does iterator invalidation occur in an unordered_map container?
sobes.tech AI
Answer from AI
Invalidation of iterators in std::unordered_map occurs when the hash table structure is changed or elements are removed.
Main cases:
- Insertion: When inserting an element, rehashing (reallocation and restructuring of the table) may be required if the load factor exceeds
max_load_factor(). In this case, all iterators, references, and pointers to elements become invalid. If rehashing does not occur, iterators to existing elements remain valid, but the iterator pointing to the end of the container (end()) may become invalid. - Deletion: Removing a single element using an iterator (
erase(pos)) invalidates only the iteratorposand references/pointers to the removed element. Iterators to other elements remain valid. Removing a range of elements (erase(first, last)) invalidates all iterators, references, and pointers in the removed range. Usingclear()or erasing by key (erase(key)) invalidates all iterators, references, and pointers to the removed elements. Iterators to other elements remain valid. - Rehashing (
rehash): Explicit call torehash()or automatic rehashing due to insertion invalidates all iterators, references, and pointers. - Reserving (
reserve): Similar to rehashing, an explicit call toreserve()may cause reallocation and invalidate all iterators, references, and pointers.
It is important to remember that in unordered_map, the order of elements is not guaranteed, and the position of elements may change regardless of iterator invalidation.
#include <unordered_map>
#include <iostream>
int main() {
std::unordered_map<int, std::string> my_map;
my_map[1] = "one";
my_map[2] = "two";
auto it = my_map.begin(); // Iterator to beginning
my_map[3] = "three"; // Insertion, may cause rehashing and invalidate `it`
// Insertion without rehashing (e.g., if load_factor is low)
// `it` may remain valid, but its position may change logically
// auto it_to_erase = my_map.find(1);
// if (it_to_erase != my_map.end()) {
// my_map.erase(it_to_erase); // Invalidates `it_to_erase`
// // Other iterators remain valid
// }
// my_map.clear(); // Invalidates all iterators
return 0;
}