CodeMIRAI
0 XP

std::map

3 min read 4 runnable examples Quiz included

A vector finds values by position: element 0, element 1. A std::map finds them by a key you choose: a name, a word, a product code. Each key appears once, with one value.

Keys and values

C++
#include <iostream>
#include <map>
#include <string>
using namespace std;

int main() {
    map<string, int> ages;           // keys are strings, values are ints
    ages["Leo"] = 31;
    ages["Asha"] = 24;
    ages["Mei"] = 28;
    cout << "Asha is " << ages["Asha"] << endl;

    ages["Asha"] = 25;               // the same key again: the value is replaced
    for (const auto& [name, age] : ages)
        cout << name << ": " << age << endl;
    cout << ages.size() << " people" << endl;
    return 0;
}
Output
Asha is 24
Asha: 25
Leo: 31
Mei: 28
3 people
  • map<string, int> maps string keys to int values.
  • ages["Leo"] = 31 adds the key, or updates it if it's already there.
  • A map keeps its keys sorted, so the loop visits Asha, Leo, Mei in alphabetical order, whatever order they were added in.
  • const auto& [name, age] unpacks each entry into its key and value. This is a structured binding, from C++17.

Looking up safely

C++
#include <iostream>
#include <map>
#include <stdexcept>
#include <string>
using namespace std;

int main() {
    map<string, double> prices = {{"apple", 0.5}, {"bread", 2.25}, {"milk", 1.2}};

    auto it = prices.find("cheese");
    if (it == prices.end()) cout << "No cheese on the list" << endl;
    else cout << "Cheese costs " << it->second << endl;

    cout << prices.count("milk") << " " << prices.count("cheese") << endl;

    cout << prices["cheese"] << endl;      // [] quietly adds cheese, priced 0
    cout << prices.size() << " items now" << endl;
    prices.erase("cheese");
    cout << prices.size() << " items after erase" << endl;

    try {
        prices.at("cake");
    } catch (const out_of_range&) {
        cout << "at() throws for a missing key" << endl;
    }
    return 0;
}
Output
No cheese on the list
1 0
0
4 items now
3 items after erase
at() throws for a missing key

There are three ways to ask about a key, and they behave differently:

  • find(key) returns an iterator to the entry, or end() if there isn't one. it->first is the key and it->second the value.
  • count(key) is 1 if the key exists and 0 if not. (C++20 adds contains, but this course targets C++17.)
  • map[key] creates the entry, with a zero value, when the key is missing. That's handy for counting and a trap for checking.

Counting words

This example's input is the cat and the hat and the bat:

C++
#include <iostream>
#include <map>
#include <string>
using namespace std;

int main() {
    map<string, int> counts;
    string word;
    while (cin >> word) counts[word]++;     // a new word starts at 0, then becomes 1

    string top;
    for (const auto& [w, n] : counts) {
        cout << w << " " << n << endl;
        if (top.empty() || n > counts[top]) top = w;
    }
    cout << "Most common: " << top << endl;
    return 0;
}
Output
and 2
bat 1
cat 1
hat 1
the 3
Most common: the

This is where [] creating missing entries pays off: counts[word]++ works for words seen before and words seen for the first time. Counting things by key is one of the most common jobs a map does.

unordered_map

C++
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;

int main() {
    unordered_map<char, int> freq;
    for (char c : string("mississippi")) freq[c]++;
    cout << "s: " << freq['s'] << ", i: " << freq['i'] << ", p: " << freq['p'] << endl;
    return 0;
}
Output
s: 4, i: 4, p: 2

unordered_map works the same way but stores keys in a hash table instead of in sorted order. Lookups are usually faster, especially for big maps, but looping over it visits keys in no particular order. Use map when you want sorted keys, and unordered_map when you only look things up.

Finished this lesson?Mark it complete to earn +20 XP and move your progress on.