std::map в C++: ассоциативный массив по ключу с практическими примерами
std::map в C++ — это ассоциативный контейнер из стандартной библиотеки, который хранит данные в виде пар ключ-значение. Если обычный массив или std::vector ищет элементы по индексу, то std::map позволяет обращаться к значению по ключу: строке, числу, дате, объекту и т.д.
Типичный поисковый запрос по этой теме — «std::map в C++ примеры». Поэтому разберём не теорию ради теории, а практические сценарии: словарь настроек, подсчёт слов, поиск элемента и безопасное обновление значения.
Что такое std::map
std::map хранит уникальные ключи в отсортированном порядке. Внутри обычно используется сбалансированное дерево, поэтому основные операции — вставка, поиск и удаление — выполняются за O(log n).
Подключается контейнер через заголовок <map>:
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<std::string, int> scores;
scores["Alice"] = 90;
scores["Bob"] = 75;
scores["Charlie"] = 82;
std::cout << scores["Alice"] << std::endl; // 90
return 0;
}
Здесь ключ — std::string, значение — int. То есть мы получаем структуру вроде «имя → баллы».
Добавление элементов в std::map
Самый простой способ — оператор []:
std::map<std::string, int> ages;
ages["Ivan"] = 25;
ages["Maria"] = 31;
Но важно понимать: если ключа нет, operator[] создаст новый элемент со значением по умолчанию. Для int это будет 0, для std::string — пустая строка.
Более явная вставка — через insert:
std::map<std::string, int> ages;
auto result = ages.insert({"Ivan", 25});
if (result.second) {
std::cout << "Элемент добавлен" << std::endl;
} else {
std::cout << "Ключ уже существует" << std::endl;
}
insert не перезаписывает значение, если ключ уже есть. Это полезно, когда случайное обновление данных недопустимо.
Обновление значения: insert_or_assign
Если нужно добавить элемент или обновить существующий, используйте insert_or_assign:
std::map<std::string, int> prices;
prices.insert_or_assign("apple", 120);
prices.insert_or_assign("apple", 135); // значение обновится
std::cout << prices["apple"] << std::endl; // 135
Этот метод хорошо показывает намерение программиста: «вставь или замени».
Поиск элемента в std::map
Новички часто проверяют наличие ключа так:
if (scores["Denis"] > 0) {
// ...
}
Это плохая идея: если ключа "Denis" нет, он будет создан автоматически со значением 0. Для безопасного поиска используйте find:
std::map<std::string, int> scores = {
{"Alice", 90},
{"Bob", 75}
};
auto it = scores.find("Bob");
if (it != scores.end()) {
std::cout << "Найдено: " << it->first
<< " = " << it->second << std::endl;
} else {
std::cout << "Ключ не найден" << std::endl;
}
Итератор it указывает на пару, где it->first — ключ, а it->second — значение.
Проверка наличия ключа через contains
Начиная с C++20, у std::map есть удобный метод contains:
std::map<std::string, int> users = {
{"admin", 1},
{"guest", 0}
};
if (users.contains("admin")) {
std::cout << "Пользователь существует" << std::endl;
}
Если вы пишете на C++17 или ниже, используйте find.
Перебор элементов map
Так как std::map хранит ключи отсортированными, обход будет идти по возрастанию ключей:
std::map<std::string, int> scores = {
{"Charlie", 82},
{"Alice", 90},
{"Bob", 75}
};
for (const auto& item : scores) {
std::cout << item.first << ": "
<< item.second << std::endl;
}
Вывод будет в алфавитном порядке по ключу: Alice, Bob, Charlie.
В C++17 можно писать ещё удобнее — через structured bindings:
for (const auto& [name, score] : scores) {
std::cout << name << ": " << score << std::endl;
}
Удаление элементов
Удалить элемент можно по ключу:
std::map<std::string, int> scores = {
{"Alice", 90},
{"Bob", 75}
};
scores.erase("Bob");
Метод erase возвращает количество удалённых элементов. Для std::map это будет 0 или 1, потому что ключи уникальны.
if (scores.erase("Bob") == 1) {
std::cout << "Элемент удалён" << std::endl;
}
Практический пример: подсчёт слов
Один из самых полезных примеров std::map — подсчёт количества повторений:
#include <iostream>
#include <map>
#include <sstream>
#include <string>
int main() {
std::string text = "cat dog cat bird dog cat";
std::istringstream input(text);
std::map<std::string, int> wordCount;
std::string word;
while (input >> word) {
wordCount[word]++;
}
for (const auto& [word, count] : wordCount) {
std::cout << word << ": " << count << std::endl;
}
return 0;
}
Здесь wordCount[word]++ работает удобно: если слова ещё нет в словаре, оно создаётся со значением 0, затем увеличивается на 1.
std::map или std::unordered_map?
У новичков часто возникает вопрос: что выбрать — std::map или std::unordered_map?
- std::map хранит ключи отсортированными и обычно работает за
O(log n). - std::unordered_map не гарантирует порядок, но в среднем ищет быстрее — за
O(1).
Выбирайте std::map, если вам нужен отсортированный обход, диапазоны ключей или стабильный порядок вывода. Если порядок не важен, а нужен максимально быстрый доступ по ключу, чаще подходит std::unordered_map.
Типичные ошибки новичков
- Использовать operator[] только для проверки. Он может создать новый элемент. Для проверки используйте
findилиcontains. - Забывать, что ключи уникальны. Если нужно хранить несколько значений на один ключ, посмотрите в сторону
std::multimapилиstd::map<Key, std::vector<Value>>. - Ожидать порядок добавления.
std::mapсортирует элементы по ключу, а не хранит их в порядке вставки. - Выбирать map «на всякий случай». Если сортировка не нужна, возможно,
unordered_mapбудет практичнее.
Рекомендации по использованию
Для начинающих хорошее правило такое: используйте std::map, когда ключи должны быть упорядочены и вам важна предсказуемость обхода. Для справочников, настроек, таблиц соответствий и подсчётов это отличный инструмент.
Если вы хотите не просто копировать примеры, а уверенно понимать контейнеры, функции, классы и современный синтаксис языка, посмотрите курс «Программирование на C++ с Нуля до Гуру» — системный путь от первых программ до уверенной разработки. Он хорошо дополняет практику со стандартной библиотекой.
Вывод
std::map в C++ — это удобный контейнер для работы с данными по ключу. Он подходит для словарей, конфигураций, подсчёта частот, таблиц соответствий и других задач, где важны уникальные ключи и отсортированный порядок. Главное — помнить про поведение operator[], использовать find для безопасного поиска и осознанно выбирать между map и unordered_map.
-
Создано 22.06.2026 17:03:09
-
Михаил Русаков

Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.