std::unordered_map Quick Reference
`std::unordered_map` is the default hash table in C++: average O(1) insert, lookup, and erase. This snippet covers insertion, the right way to test for membership without inserting a default, iteration, and structured bindings (C++17) for clean key/value loops. Use it whenever you need a dictionary; reach for `std::map` only when you need keys in sorted order.
872 views
5
#include <iostream>
#include <unordered_map>
#include <string>
int main() {
std::unordered_map<std::string, int> ages;
ages["ada"] = 36;
ages["linus"] = 54;
ages.insert({"margaret", 88});
std::cout << "ada=" << ages["ada"] << " size=" << ages.size() << "\n";
return 0;
}operator[] inserts a default-constructed value (here 0) if the key is missing, then returns a reference to it. That makes assignment as simple as m[key] = value, but it also means cout << m["missing"] will INSERT an empty entry as a side effect. For pure look-ups always use find or contains (next accordion) to avoid that surprise. insert({k, v}) only adds when the key is new and returns a pair<iterator, bool> you can inspect to see whether the insert happened.
#include <iostream>
#include <unordered_map>
#include <string>
void demoLookup(const std::unordered_map<std::string, int>& ages) {
// C++20 has m.contains(key); GCC 9.2 (C++17) does not.
auto it = ages.find("ada");
if (it != ages.end()) {
std::cout << "found ada=" << it->second << "\n";
} else {
std::cout << "missing\n";
}
// count() returns 0 or 1 for an unordered_map; cheaper than find for booleans.
if (ages.count("ghost") == 0) std::cout << "ghost is absent\n";
}
int main() {
std::unordered_map<std::string, int> ages = {{"ada", 36}, {"linus", 54}};
demoLookup(ages);
return 0;
}find(key) returns an iterator pointing at the entry or end() if missing. The classic idiom is auto it = m.find(k); if (it != m.end()) { use it->second; }. Since C++20, m.contains(k) reads more clearly, but the GCC 9.2 / C++17 compiler in the test runner does not have it; count(key) is the portable fallback that returns 0 or 1. Never use m[key] for membership testing because it inserts a default value as a side effect, silently growing the map.
#include <iostream>
#include <unordered_map>
#include <string>
void demoIterate() {
std::unordered_map<std::string, int> scores;
scores.insert({"ada", 100});
scores.insert({"linus", 92});
scores.insert({"margaret", 99});
// Iterate with the classic iterator form. C++17 also supports structured
// bindings: for (const auto& [name, score] : scores) { ... }
for (auto it = scores.begin(); it != scores.end(); ++it) {
std::cout << it->first << "=" << it->second << "\n";
}
// Erase while iterating: reassign from erase() because the old iterator
// becomes invalid for the erased entry.
for (auto it = scores.begin(); it != scores.end(); ) {
if (it->second < 95) it = scores.erase(it);
else ++it;
}
std::cout << "after prune size=" << scores.size() << "\n";
}
int main() {
demoIterate();
return 0;
}The classic iterator form it->first / it->second works on every C++ standard; C++17 added the cleaner for (const auto& [k, v] : map) structured-binding form, which most modern code uses. Iteration order in unordered_map is implementation-defined and may change after rehashes, so do not rely on it; use std::map if you need sorted keys. When erasing during iteration, always reassign from erase() because the old iterator becomes invalid; the C++ standard makes erase return the iterator to the next element specifically to support this pattern.
