C++ / CHAPTER 06

Maps, lookup, and accidental insertion

Intermediate

Choose associative operations according to whether they may modify the container.

By the end of this chapter

  • Count keyed values
  • Use find for noninserting lookup
  • Distinguish ordering from hashing

The idea

std::map stores unique keys in comparator order and supports logarithmic lookup. std::unordered_map uses hashing and does not promise sorted iteration. Pick the container according to the operations and ordering your interface requires, rather than assuming that every dictionary iteration has the same order.

The indexing operator on a map is convenient for accumulating counts because a missing mapped integer is value-initialized to zero. That same insertion is a bug when a read-only existence check must leave the map unchanged. Use find and compare the iterator with end for a noninserting lookup. Never dereference the end iterator. An explicit lookup policy also keeps a missing key distinct from a present key whose value is zero.

C++ example
#include <iostream>
#include <map>
#include <string>
int main() {
  std::map<std::string, int> counts;
  ++counts["pear"]; ++counts["pear"];
  auto it = counts.find("apple");
  std::cout << counts.size() << ' ' << (it == counts.end());
}
Result
1 1

find does not insert apple, so the map still contains one key.

Try it yourself

Count words and implement a separate lookup that reports absence without inserting a key.

Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.

CHECK YOUR UNDERSTANDING

Chapter checkpoint

Which operation checks for a missing key without inserting it?