Question

How to Iterate Through std::map in C++

cppfor-loopiteratorstdmaprange-based-loop

Question

How can I iterate over every element in a std::map<std::string, int> when I do not know its keys or values in advance? In particular, how do I access the key and value for each iterator position?

void output(std::map<std::string, int> table)
{
    std::map<std::string, int>::iterator it;

    for (it = table.begin(); it != table.end(); it++)
    {
        // How do I access each key and value?
    }
}

Short Answer

By the end of this page, you will know that each std::map element is a key-value pair, how to access its .first and .second members, and how to use modern range-based loops safely and clearly.

Concept

std::map<Key, Value> stores key-value pairs. For this map:

std::map<std::string, int> table;
  • The key type is std::string.
  • The value type is int.
  • Each individual map element is effectively a std::pair<const std::string, int>.

A pair has two named members:

  • .first — the key
  • .second — the mapped value

Therefore, when an iterator points at an element, dereferencing it (*it) gives access to that pair:

it->first   // the string key
it->second  // the integer value

The arrow operator is shorthand for dereferencing the iterator and then accessing a member:

(*it).first   // equivalent to it->first
(*it).second  // equivalent to it->second

Maps are ordered by key. With the default comparator, iteration visits string keys in ascending lexicographical order. This is useful when you need predictable, sorted traversal rather than insertion order.

Mental Model

Think of a std::map as a sorted filing cabinet.

  • Every drawer label is a key ("apples").
  • The item count inside that drawer is the value (4).
  • An iterator is your finger pointing to one drawer.

When your finger points at a drawer:

  • it->first reads its label.
  • it->second reads or updates what is inside it.

Calling ++it moves your finger to the next drawer in sorted label order.

Take Quiz

Syntax and Examples

The classic iterator form accesses the current pair through it:

#include <iostream>
#include <map>
#include <string>

void output(const std::map<std::string, int>& table)
{
    for (std::map<std::string, int>::const_iterator it = table.begin();
         it != table.end();
         ++it)
    {
        std::cout << it->first << ": " << it->second << '\n';
    }
}

const std::map<std::string, int>& is used because this function only reads the map:

  • const prevents accidental modification.
  • & avoids copying the entire map when calling the function.
  • const_iterator matches a const map and allows reading its elements.

For C++11 and later, a range-based for loop is usually easier to read:

for (const auto& entry : table)
{
    std::cout << entry.first << ": " << entry.second << '\n';
}

For C++17 and later, structured bindings give the key and value their own names:

for (const auto& [key, value] : table)
{
    std::cout << key << ": " << value << '\n';
}

Example output for a map containing {"banana", 2}, {"apple", 5}, and {"pear", 1} is:

apple: 5
banana: 2
pear: 1

The order is alphabetical by key, not the order in which the values were inserted.

Step by Step Execution

Consider this code:

std::map<std::string, int> scores{
    {"Mia", 90},
    {"Ava", 95}
};

for (auto it = scores.begin(); it != scores.end(); ++it)
{
    std::cout << it->first << " scored " << it->second << '\n';
}

Execution proceeds as follows:

  1. scores stores two pairs: ("Mia", 90) and ("Ava", 95).
  2. scores.begin() returns an iterator pointing at the first key in sorted order: "Ava".
  3. it != scores.end() is true because it points to a real element.
  4. it->first is "Ava", and it->second is 95; the first line is printed.
  5. ++it advances the iterator to the pair for "Mia".
  6. The condition is true again, and the second line is printed.
  7. Another ++it advances the iterator to scores.end(), a position just after the last element.
  8. The condition becomes false, so the loop stops.

Output:

Ava scored 95
Mia scored 90

Real World Use Cases

Iterating through a map is useful whenever data is indexed by a unique name, identifier, or code:

  • Configuration settings: print or validate settings such as "theme" -> 2.
  • Inventory: process product names and stock counts.
  • API aggregation: iterate through response headers or request parameters.
  • Word-frequency analysis: print each word and its number of occurrences.
  • User statistics: walk through user IDs and their scores or balances.
  • Reporting: produce a deterministic report because std::map traverses keys in sorted order.
Take Quiz

Real Codebase Usage

In production C++ code, range-based loops with references are commonly preferred for simple traversal:

for (const auto& [name, count] : inventory)
{
    log(name, count);
}

Use const auto& when only reading. It avoids copying each key-value pair, which matters if keys or values are large objects.

When updating mapped values, use a non-const reference to the entry. The key remains immutable through a map iterator:

for (auto& [name, count] : inventory)
{
    if (count < 0)
    {
        count = 0;
    }
}

A common validation pattern is to return early when a required key is absent, then use find when you only need one key:

auto it = settings.find("timeout");
if (it == settings.end())
{
    return;
}

int timeout = it->second;

Use full iteration when every entry must be processed. Use find when searching for a specific key.

Common Mistakes

Using it.first instead of it->first

An iterator is not the pair itself. This is incorrect:

std::cout << it.first; // Error

Use either form below:

std::cout << it->first;
std::cout << (*it).first;

Dereferencing end()

end() does not point to an element. Never do this:

auto it = table.end();
std::cout << it->second; // Undefined behavior

Only dereference an iterator after confirming it is not equal to end().

Copying the map unnecessarily

The original function parameter copies the entire map:

void output(std::map<std::string, int> table)

For read-only output, prefer:

void output(const std::map<std::string, int>& table)

Trying to modify the key

Map keys are treated as const because changing a key could break the map's sorted structure:

for (auto& entry : table)
{
    // entry.first = "new key"; // Error
    entry.second += 1;           // Valid
}

Using table[key] merely to check for a key

operator[] inserts a new entry if the key is missing:

if (table["unknown"] == 0) { }

Use find or contains instead when you do not want insertion:

if (table.find("unknown") != table.end()) { }

Erasing while using a simple increment loop

Erasing invalidates the iterator being erased. Use the iterator returned by erase:

for (auto it = table.begin(); it != table.end();)
{
    if (it->second == 0)
    {
        it = table.erase(it);
    }
    else
    {
        ++it;
    }
}

Comparisons

ApproachC++ versionBest useAccess to key and value
Explicit iteratorAll modern C++ versionsErasing entries or manually controlling movementit->first, it->second
Range-based loopC++11+Straightforward traversalentry.first, entry.second
Structured bindingsC++17+Clearest read-only or update loopskey, value
findAll modern C++ versionsLooking up one known keyit->second after checking end()

std::map and std::unordered_map both store key-value pairs, but their iteration behavior differs:

ContainerIteration orderTypical lookup behaviorUse when
std::mapSorted by keyO(log n)You need sorted keys or ordered operations
std::unordered_mapNo guaranteed orderAverage O(1)You primarily need fast key lookups and do not need ordering
Take Quiz

Cheat Sheet

std::map<std::string, int> table;
TaskCode
Get first iteratorauto it = table.begin();
Detect endit == table.end()
Read keyit->first
Read or change valueit->second
Move forward++it
Read every entry, C++11+for (const auto& entry : table)
Name key and value, C++17+for (const auto& [key, value] : table)
Find one keyauto it = table.find(key);

Rules to remember:

  • Do not dereference table.end().
  • Map keys are immutable through iterators; mapped values can be changed in a non-const map.
  • Pass a map as const std::map<Key, Value>& when a function only reads it.
  • std::map iterates in sorted key order.

FAQ

How do I get the key and value from a std::map iterator?

Use it->first for the key and it->second for the value.

Why is it->first used instead of it.first?

it is an iterator, which behaves like a pointer to an element. it->first accesses the pair that the iterator points to.

Can I change a value while iterating through a map?

Yes, if the map and iterator are non-const. Assign to it->second or to the value binding in for (auto& [key, value] : map).

Can I change a map key while iterating?

No. A map's keys are immutable through iterators because their order defines the container's internal structure. To change a key, erase the old entry and insert a new one.

Does std::map preserve insertion order?

No. It iterates in sorted order according to its key comparator, ascending order by default.

Should I use it++ or ++it in a map loop?

Prefer ++it. For iterators, postfix increment (it++) may create an unnecessary temporary copy.

Is const auto& [key, value] safe in a range-based loop?

Yes. It creates read-only references to each map entry without copying it. It requires C++17.

What happens if I access table["missing"]?

A new entry with that key is inserted, using a default value such as 0 for int. Use find if you only want to test whether the key exists.

Take Quiz

Mini Project

Description

Build a small inventory-report function. A store keeps item names as map keys and stock counts as values. Your function will loop through the entire map, print each item, and calculate the total number of units in stock.

Goal

Display every inventory entry in sorted item-name order and return the total stock count.

Requirements

  1. Create a std::map<std::string, int> containing at least three inventory items.
  2. Write a function that accepts the map without copying it.
  3. Loop through every key-value pair in the map.
  4. Print each item name and its quantity.
  5. Return and print the sum of all quantities.
Take Quiz

Keep learning

Related questions

View more