Home C++ Tutorial on std::unordered_map in C++

Tutorial on std::unordered_map in C++

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:

  1. Basic Syntax and Initialization of std::unordered_map
  2. Inserting and Accessing Elements using insert, emplace, and operator[]
  3. Checking for Existence using find and count
  4. Removing Elements using erase
  5. Iterating Through Elements with range-based for loops and iterators
  6. Common Member Functions like size, empty, and clear
  7. 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++.

You may also like