15.10. Key-value associations with std::mapΒΆ

std::map is declared in <map>. Each element associates a unique key with a value. Keys are sorted by the comparison function; the default order for strings is lexicographical. A map of names to counts lets us update a count without searching a vector of records ourselves.

Example c192_map_counts
 1#include <cstddef>
 2#include <iostream>
 3#include <map>
 4#include <string>
 5#include <vector>
 6
 7int main() {
 8    std::vector<std::string> visits{"Boston", "Chicago", "Boston"};
 9    std::map<std::string, std::size_t> counts;
10    for (const auto& city_name : visits) {
11        ++counts[city_name];
12    }
13    for (const auto& [city_name, count] : counts) {
14        std::cout << city_name << ": " << count << '\n';
15    }
16}

The structured binding [city_name, count] names the key and mapped value of each pair. The reference avoids copying the strings during iteration.

Unlike a vector subscript, a map subscript names a key, not a position. counts[key] inserts a missing key with a value-initialized value (zero for std::size_t), and returns a reference to that value. That behavior is useful for counting, but can be a bug in code that only intended to look up a value.

Example c192_map_lookup
 1#include <iostream>
 2#include <map>
 3#include <string>
 4
 5int main() {
 6    std::map<std::string, int> distances{{"Boston", 1100}, {"Chicago", 700}};
 7    auto position = distances.find("Seattle");
 8    if (position == distances.end()) {
 9        std::cout << "unknown distance\n";
10    } else {
11        std::cout << position->second << '\n';
12    }
13    std::cout << distances.size() << '\n';
14}

find and contains do not insert. at(key) returns an existing mapped value, or throws std::out_of_range if the key is absent. A map can also be read through a const reference using those members; operator[] is not available on a const map because it might insert.

insert_or_assign(key, value) explicitly inserts or replaces a mapped value. try_emplace(key, value) inserts only when the key is absent. erase(key) removes a key and its value. Lookup, insertion, and removal by key take logarithmic time. As with sets, an unordered counterpart is available when hashing rather than sorted iteration fits the task.

We want to open a file and parse its data into our program. What library do we need to include?