Start learning free

LESSON 98 OF 343 · DICTIONARIES

Accessing Dictionary Values in C++: [], at() and count()

Lesson Read the full explanation

In C++, you access values in an unordered_map using square bracket notation or at():

unordered_map<string, int> scores;
scores["Alice"] = 95;
scores["Bob"] = 87;

int aliceScore = scores["Alice"];  // 95
int bobScore = scores.at("Bob");   // 87

Note: scores["key"] inserts a default value (0) if the key doesn't exist. Use at() to get an exception instead, or count() to check existence:

if (scores.count("Alice") > 0) {
    cout << scores["Alice"];
}

Assignment
Follow the Coding Tutorial and access Alice's score from scores!


Hint
Use scores["Alice"] and assign it to aliceScore.

STEP 1 OF 1
    Ctrl + Enter to check

    C++ · DICTIONARIES

    Accessing Dictionary Values in C++, explained

    Looking up a value by key

    An unordered_map answers the question "what value goes with this key?" quickly. C++ gives you several ways to ask it, and they differ in what happens when the key is missing. Knowing that difference is the main point of this lesson.

    Take this map:

    unordered_map<string, int> scores;
    scores["Alice"] = 95;
    scores["Bob"] = 87;
    

    Square brackets

    The operator [] returns the value stored under the key:

    int aliceScore = scores["Alice"];   // 95
    

    It is short and works for both reading and writing, but it has a side effect. If the key is not in the map, [] inserts it with a default-constructed value, which is 0 for an int, and returns that. After int x = scores["Zed"];, x is 0 and the map has grown from two entries to three. A lookup meant to check whether someone exists has just added them.

    This also means [] cannot be used on a const map, because it might need to change the map.

    The at() method

    The method at() reads without inserting. When the key is missing it throws a std::out_of_range exception:

    int bobScore = scores.at("Bob");   // 87
    

    Use at() when a missing key means a bug and you want the program to say so, rather than carry on with a made-up zero. If the key might legitimately be absent, catch the exception or check first.

    Checking before you read

    Two tools test for a key without changing the map:

    • count(key) returns how many entries have that key. Keys are unique, so the answer is 0 or 1.
    • find(key) returns an iterator that points at the entry, or scores.end() when it is missing. It lets you test and read with a single lookup.
    if (scores.count("Alice") > 0) {
        cout << scores["Alice"];
    }
    
    auto it = scores.find("Bob");
    if (it != scores.end()) {
        cout << it->second;   // 87
    }
    

    For an iterator, it->first is the key and it->second is the value. After the check passes, using [] is safe, since the key is known to exist. In a loop that runs many times, find avoids searching twice.

    A default for missing keys

    Often the real need is "the value if present, otherwise some fallback", without growing the map. Write it with find and a conditional expression:

    auto it = scores.find("Zed");
    int zedScore = (it != scores.end()) ? it->second : -1;   // -1, and the map is unchanged
    

    The map has no built-in method for this, so the pattern is worth memorising. It reads the map once, it never inserts, and the fallback value is yours to choose. That last point matters when 0 is a legitimate score and cannot double as "missing".

    Which one to choose

    You wantUse
    A value, and a missing key is a bugat(key)
    To know if a key existscount(key) or find(key)
    Read it if present, else do something elsefind(key)
    Add or overwrite a value[key] = value

    The exercise, step by step

    The editor starts with a map named scores that holds Alice, Bob and Charlie. The task is to read Alice's score into a variable.

    1. Declare an int named aliceScore. The score is a whole number, matching the map's value type.
    2. Assign it scores["Alice"]. The key is the string "Alice" in double quotes.
    unordered_map<string, int> scores;
    scores["Alice"] = 95;
    scores["Bob"] = 87;
    scores["Charlie"] = 72;
    
    int aliceScore = scores["Alice"];
    

    The key exists, so aliceScore is 95 and the map is unchanged, still with three entries. scores.at("Alice") would give the same answer here.

    Common mistakes

    • Reading a key that is not there with []. You silently get 0 and add an entry. A typo like scores["alice"] does not fail, because keys are case sensitive and "alice" is a different key.
    • Using count as a lookup. It tells you whether the key exists, not what the value is.
    • Leaving an exception uncaught. at() on a missing key ends the program if nothing catches the exception.
    • Treating a stored 0 as "missing". A key can really hold 0, so test with count or find, not by comparing the value to 0.

    Key takeaways

    • m[key] reads, but inserts a default value if the key is missing.
    • m.at(key) throws std::out_of_range instead of inserting.
    • Use count or find to test for a key without changing the map.
    Keep going with C++About 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free