C++ Basics: Refresh Iterators After Reserving an Unordered Map
Separate iterator invalidation from element reference stability when reserving hash-table capacity.
Prepare a scratch directory
Tested on Linux x86_64 with GCC 14.2.0. Install a C++20-capable compiler and its standard-library headers, with g++ on PATH. You also need Bash, a text editor, and the mktemp, rm, and rmdir utilities. No third-party library is required.
Keep the same terminal open. Stop if setup fails, before saving the source:
start_directory="$PWD"
work_directory="$(mktemp -d)" || exit 1
cd -- "$work_directory" || exit 1Run the example
Save this as unordered-map-rehash-handles-demo.cpp:
#include <iostream>
#include <string>
#include <unordered_map>
int main() {
std::unordered_map<std::string, int> counters{{"requests", 7}};
int& request_count = counters.at("requests");
counters.reserve(100);
++request_count;
const auto current = counters.find("requests");
std::cout << "Retained reference: " << request_count << '\n';
std::cout << "Fresh iterator: " << current->second << '\n';
std::cout << "Entries: " << counters.size() << '\n';
}Compile and run it. The second command runs only after compilation succeeds:
g++ -std=c++20 -Wall -Wextra -Werror -pedantic unordered-map-rehash-handles-demo.cpp -o unordered-map-rehash-handles-demo &&
./unordered-map-rehash-handles-demoObserved output:
Retained reference: 8
Fresh iterator: 8
Entries: 1Read the result
The reference still identifies the same mapped value after reserve. The example obtains its iterator afterward, so it never dereferences a stale iterator.
Apply it carefully
Rehashing invalidates iterators but not references or pointers to retained elements. Treat reserve as an iterator boundary and reacquire iterators. Erasing an element still invalidates its references. Reserve plans buckets for a requested element count; it neither inserts elements nor promises an exact bucket count. Future growth can rehash again.
The C++ working draft documents the relevant container rules. This example uses only features available in C++20, even though the linked draft also includes newer additions.
Clean up
Remove only the source and executable created here, then remove the empty practice directory:
rm -- unordered-map-rehash-handles-demo.cpp unordered-map-rehash-handles-demo
cd -- "$start_directory" || exit 1
rmdir -- "$work_directory"
unset start_directory work_directoryIf the directory is not empty, inspect its remaining contents before removing anything else.
Acknowledgements
This post was created with assistance from AI.