std::unordered_map is a part of the C++ Standard Library available under the <unordered_map> header. It provides a hash table-based implementation of key-value pairs, where each key is unique and mapped to a specific value.
Since std::unordered_map stores elements in an unordered manner using hashing, it provides efficient insertion, deletion, and search operations with an average time complexity of O(1)O(1).
In this tutorial, we’ll cover:
1. Basic Syntax and Initialization
To use std::unordered_map, include the <unordered_map> header.
#include <iostream> #include <unordered_map> int main() { // Initialize an empty unordered map std::unordered_map<std::string, int> wordCount; // Initialize with values std::unordered_map<std::string, int> ageMap = {{"Alice", 25}, {"Bob", 30}, {"Charlie", 35}}; // Print initial elements std::cout << "Initial ageMap:" << std::endl; for (const auto& pair : ageMap) { std::cout << pair.first << ": " << pair.second << std::endl; } return 0; }
2. Inserting and Accessing Elements
You can insert elements into unordered_map using insert, operator[], or emplace. Using operator[] allows both insertion and retrieval of values associated with a specific key.
#include <iostream> #include <unordered_map> int main() { std::unordered_map<std::string, int> ageMap; // Insert elements using insert ageMap.insert({"Alice", 25}); ageMap.insert({"Bob", 30}); // Insert or access using operator[] ageMap["Charlie"] = 35; ageMap["David"] = 40; // Accessing elements std::cout << "Alice's age: " << ageMap["Alice"] << std::endl; std::cout << "Bob's age: " << ageMap["Bob"] << std::endl; return 0; }
Output:
Alice's age: 25 Bob's age: 30
Note: Using operator[] on a key that doesn’t exist creates a new entry with the default value (0 for integers).
3. Checking for Existence and Counting Keys
Use the find function to check if a key exists in the map, and count to check if a key exists and its frequency.
#include <iostream> #include <unordered_map> int main() { std::unordered_map<std::string, int> ageMap = {{"Alice", 25}, {"Bob", 30}}; // Check existence using find if (ageMap.find("Alice") != ageMap.end()) { std::cout << "Alice is in the map." << std::endl; } else { std::cout << "Alice is not in the map." << std::endl; } // Check existence using count if (ageMap.count("Charlie") > 0) { std::cout << "Charlie is in the map." << std::endl; } else { std::cout << "Charlie is not in the map." << std::endl; } return 0; }
Output:
Alice is in the map. Charlie is not in the map.
4. Removing Elements
You can remove elements from an unordered_map using the erase function by key or by iterator.
#include <iostream> #include <unordered_map> int main() { std::unordered_map<std::string, int> ageMap = {{"Alice", 25}, {"Bob", 30}, {"Charlie", 35}}; // Remove an element by key ageMap.erase("Bob"); // Print map after removal std::cout << "Map after removing 'Bob':" << std::endl; for (const auto& pair : ageMap) { std::cout << pair.first << ": " << pair.second << std::endl; } return 0; }
Output:
Map after removing 'Bob': Alice: 25 Charlie: 35
5. Iterating Through an unordered_map
You can use a range-based for loop or an iterator to go through all elements in the unordered_map. Keep in mind that elements are not stored in any specific order.
#include <iostream> #include <unordered_map> int main() { std::unordered_map<std::string, int> ageMap = {{"Alice", 25}, {"Bob", 30}, {"Charlie", 35}}; // Range-based for loop std::cout << "Using range-based for loop:" << std::endl; for (const auto& pair : ageMap) { std::cout << pair.first << ": " << pair.second << std::endl; } // Using an iterator std::cout << "Using iterator:" << std::endl; for (auto it = ageMap.begin(); it != ageMap.end(); ++it) { std::cout << it->first << ": " << it->second << std::endl; } return 0; }
Output (order may vary):
Using range-based for loop: Alice: 25 Bob: 30 Charlie: 35 Using iterator: Alice: 25 Bob: 30 Charlie: 35
6. Common Member Functions
- size(): Returns the number of elements.
- empty(): Checks if the map is empty.
- clear(): Removes all elements from the map.
#include <iostream> #include <unordered_map> int main() { std::unordered_map<std::string, int> ageMap = {{"Alice", 25}, {"Bob", 30}}; // Size of the map std::cout << "Size of ageMap: " << ageMap.size() << std::endl; // Check if map is empty if (!ageMap.empty()) { std::cout << "ageMap is not empty." << std::endl; } // Clear the map ageMap.clear(); std::cout << "Size of ageMap after clearing: " << ageMap.size() << std::endl; return 0; }
Output:
Size of ageMap: 2 ageMap is not empty. Size of ageMap after clearing: 0
7. Using Custom Hash Functions and Comparators
You can use std::unordered_map with custom types by defining a custom hash function and an equality function.
#include <iostream> #include <unordered_map> struct Point { int x, y; bool operator==(const Point& other) const { return x == other.x && y == other.y; } }; // Custom hash function struct PointHash { std::size_t operator()(const Point& p) const { return std::hash<int>()(p.x) ^ (std::hash<int>()(p.y) << 1); } }; int main() { // Define an unordered_map of Points with custom hash function std::unordered_map<Point, std::string, PointHash> pointMap; // Insert points pointMap[{1, 2}] = "Point A"; pointMap[{3, 4}] = "Point B"; pointMap[{1, 2}] = "Point C"; // Updates existing point // Print points in the map std::cout << "Points in pointMap:" << std::endl; for (const auto& pair : pointMap) { std::cout << "(" << pair.first.x << ", " << pair.first.y << "): " << pair.second << std::endl; } return 0; }
Output:
Points in pointMap: (1, 2): Point C (3, 4): Point B
In this example:
- Point is a custom structure with x and y coordinates.
- PointHash defines a custom hash function that combines x and y to create a unique hash.
- The custom hash function is provided as a third template argument to unordered_map, allowing it to handle Point objects.
Summary
In this tutorial, we covered:
- Basic Syntax and Initialization of std::unordered_map
- Inserting and Accessing Elements using insert, emplace, and operator[]
- Checking for Existence using find and count
- Removing Elements using erase
- Iterating Through Elements with range-based for loops and iterators
- Common Member Functions like size, empty, and clear
- Using Custom Hash Functions and Comparators for handling custom data types
std::unordered_map is an ideal container when you need a fast hash-based map with unique keys and efficient average performance for insertion, deletion, and lookups, making it highly useful for various applications in C++.