unordered_map & unordered_set
Basic usage
unordered_map_basics.cpp
#include <unordered_map>
#include <iostream>
#include <string>
int main() {
std::unordered_map<std::string, int> ages;
ages["Alice"] = 30;
ages["Bob"] = 25;
ages.insert({"Carol", 35});
// Iteration order is UNSPECIFIED — do not rely on it.
for (const auto& [name, age] : ages) {
std::cout << name << ": " << age << std::endl;
}
if (ages.find("Bob") != ages.end()) {
std::cout << "Found Bob" << std::endl;
}
ages.erase("Bob");
std::cout << ages.count("Bob") << std::endl; // 0
return 0;
}unordered_set_basics.cpp
#include <unordered_set>
#include <iostream>
int main() {
std::unordered_set<int> nums = {30, 10, 20, 10}; // duplicate ignored
std::cout << nums.size() << std::endl; // 3
if (nums.find(20) != nums.end()) {
std::cout << "20 is present" << std::endl;
}
return 0;
}map vs. unordered_map
Property | std::map / std::set | std::unordered_map / std::unordered_set |
|---|---|---|
Underlying structure | Balanced binary tree (red-black tree) | Hash table |
Iteration order | Sorted by key | Unspecified — do not rely on it |
Average time complexity | O(log n) for insert/find/erase | O(1) for insert/find/erase |
Worst-case time complexity | O(log n) — guaranteed | O(n) — possible with many hash collisions |
Memory overhead | Tree node pointers (parent, left, right) | Hash table buckets, often with extra reserved capacity |
Key requirement | Must support | Must support |
When to choose which
Custom key types need a hash function
custom_hash.cpp
#include <unordered_set>
#include <functional>
struct Point {
int x, y;
bool operator==(const Point& other) const {
return x == other.x && y == other.y;
}
};
// Specializing std::hash lets Point be used as an unordered_set/unordered_map key.
namespace std {
template <>
struct hash<Point> {
size_t operator()(const Point& p) const {
return hash<int>()(p.x) ^ (hash<int>()(p.y) << 1);
}
};
}
int main() {
std::unordered_set<Point> points;
points.insert({1, 2});
points.insert({3, 4});
return 0;
}Hash-table based; average O(1), worst-case O(n) for insert/find/erase.
No ordering guarantee — never assume iteration order is stable or sorted.
Custom key types need
operator==and astd::hashspecialization (or custom hasher).