Skip to content
std::map and std::unordered_map
step 1/5

Reading — step 1 of 5

Learn

~2 min readSTL Collections

std::map and std::unordered_map

Key → value lookup is the other half of programming (the first half being "a list of things"), and C++ ships two flavors with one API: std::map keeps keys sorted (a balanced tree underneath, O(log n)), std::unordered_map is a hash table (O(1) average, arbitrary order). Same operations; choosing between them is a one-question quiz: does output order matter?

The API

#include <map>

std::map<std::string, int> ages;
ages["alice"] = 30;              // insert or overwrite
ages["bob"] = 25;

ages["alice"]                    // 30
ages.count("carol")              // 0 or 1 — the existence test
ages.erase("bob");
ages.size();

The operator[] surprise — read this twice

m[key] on a missing key doesn't fail: it inserts the key with a default value (0 for ints, "" for strings) and returns it. Feature and footgun in one:

std::map<std::string, int> counts;
counts["apple"]++;               // absent → inserted as 0 → incremented to 1

That's the counting idiom — one line, no existence check, the same move as Rust's entry().or_insert(0) and Go's zero-value read. It powers your exercise.

The footgun: if (m["carol"] > 0) creates carol while asking about her — mutating the map during a read, growing it with ghost entries. Read-only checks use count or find:

if (ages.count("carol")) { … }               // exists?
auto it = ages.find("carol");                // find returns an iterator
if (it != ages.end()) {
    std::cout << it->second;                 // ->first = key, ->second = value
}

(That it->first/it->second pattern — map entries are std::pairs — reads oddly at first and then you see it everywhere forever.)

Iteration — and the ordering superpower

for (const auto& kv : counts) {
    std::cout << kv.first << ": " << kv.second << "\n";
}

Here the two flavors diverge: std::map iterates in sorted key order — guaranteed. Alphabetical word counts, leaderboards by ID, any "print grouped results in order" task: map does the sorting as a side effect of existing. unordered_map iterates in whatever order hashing produced (don't even expect it to be stable). Hence the working rule: output ordered → map; pure speed, order irrelevant → unordered_map. Graders print in order more often than not, which makes map the safer default here — a genuinely useful inversion of the "always hash" instinct other languages teach.

Your exercise: Distinct Words

Count the distinct words in the input. A map's key-set is a set, so:

std::map<std::string, int> seen;
std::string w;
while (std::cin >> w) {
    seen[w]++;                   // counting idiom; duplicates just re-count
}
std::cout << seen.size() << "\n";

size() counts keys — insert "apple" ten times, it's one key. (C++ also has literal std::set<std::string>insert and size, no values — either is idiomatic here; the map version practices the counting idiom you'll need the day the exercise asks how many of each, which is this exercise's big sibling and interview-question form.)

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…