Start learning free

LESSON 126 OF 667 · DICTIONARIES

Reading a Missing Key with a Default in C++

Lesson Read the full explanation

TL ; DR:

Start with the default. Then an if with count replaces it with the value, when the key is there.


unordered_map<string, int> points = {{"Ana", 7}};

int score = 0;
if (points.count("Ben") > 0) {
    score = points["Ben"];
}
cout << score << endl;   // 0


Full lesson:

A missing key often means "none yet". A player with no points yet has 0 points.

points["Ben"] gives 0 too, but it does one more thing. On a missing key, [] adds the key, with 0.

So reading with [] changes the map. points.size() would go from 1 to 2.

The if reads points["Ben"] only when the key is already there. So points keeps one key.

With "Ana", the same code gives 7.


Your task

stock counts the fruit in a shop. The code reads and prints the pears.

There are no plums yet. Declare an int named plums at 0. Then use an if with count to read stock["plums"] when the key is there.

Then print the plums line, the same way as the pears line.

Expected output:

We have 2 pears
We have 0 plums
STEP 1 OF 3
    Ctrl + Enter to check

    C++ · DICTIONARIES

    Dictionary Default Value in C++, explained

    When a key may be missing

    In many programs, a missing key means "none yet". A shop with no plums has 0 plums, and the map simply has no "plums" entry. So you want a value, 0, even when the key is absent.

    The square brackets seem to do that. For an unordered_map<string, int>, stock["plums"] gives 0 for a missing key. But it also does something else: it adds the key to the map, with the value 0. So a map with one entry now has two, and stock.size() goes from 1 to 2. A read has changed the map.

    The safe pattern: default first, then check

    Start with the default in a variable. Then use count to read the real value only when the key is already there.

    unordered_map<string, int> stock = {{"apples", 5}};
    int plums = 0;
    if (stock.count("plums") > 0) {
        plums = stock["plums"];
    }
    cout << plums << endl;   // 0
    

    Here the key is missing, so the if body is skipped. plums stays at its default of 0, and stock still has one key. Running the same pattern for "apples" sets the variable to 5.

    Other ways to read a missing key

    • stock.at("plums") does not add anything. On a missing key it throws an out_of_range exception, which ends the program unless you catch it.
    • stock.find("plums") returns stock.end() for a missing key, which you can compare and then read through it->second.

    This lesson uses the count pattern, because it reads the same way as the key check you already know.

    The exercise: counting fruit

    The map stock counts the fruit in a shop: 5 apples and 2 pears. The starter code already reads and prints the pears. The task is to do the same for plums, which are not in the map:

    1. Declare int plums = 0;, the default.
    2. Write an if that checks stock.count("plums") > 0. Inside it, set plums to stock["plums"].
    3. Print the plums line like the pears line: We have, the number, then plums.
    unordered_map<string, int> stock = {{"apples", 5}, {"pears", 2}};
    
    int pears = stock["pears"];
    cout << "We have " << pears << " pears" << endl;
    
    int plums = 0;
    if (stock.count("plums") > 0) {
        plums = stock["plums"];
    }
    cout << "We have " << plums << " plums" << endl;
    

    The output is:

    We have 2 pears
    We have 0 plums
    

    After this code, stock still holds two entries. If the code had read stock["plums"] directly, the line would print the same 0, but the map would silently have a third entry, plums with 0.

    Why the order matters

    Declare the default before the if, not inside it. A variable declared inside the braces would disappear at the closing brace, and the final cout line could not use it. With the declaration above the if, one print statement works for both cases, whether the key was there or not.

    The same shape, "default, then overwrite if present", works for any type of value. With unordered_map<string, string>, the default could be "unknown".

    Key takeaways

    • On a missing key, m[key] inserts the key with a default value (0 for numbers).
    • To read without changing the map, set the default first and read m[key] only inside an if (m.count(key) > 0).
    • The default can be any value that makes sense for your data: 0 for a count, an empty string for text.
    Keep going with C++500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free