Перейти к содержимому
Теория · Контейнеры и итераторы · урок 8 из 11

Как выбрать контейнер

Узнать, есть ли число в векторе, можно только перебором: цикл сравнивает с этим числом каждый элемент. std::set отвечает на тот же вопрос одним вызовом contains:

C++
#include <iostream>
#include <set>
#include <vector>

int main() {
    std::vector<int> v{7, 3, 9};
    bool in_vector = false;
    for (int x : v) {
        if (x == 9) {
            in_vector = true;
        }
    }
    std::set<int> s{7, 3, 9};
    std::cout << in_vector << ' ' << s.contains(9) << '\n';  // 1 1
}

Для трёх чисел разницы не видно. Но перебор миллиона элементов делает до миллиона сравнений, а std::set находит ключ среди миллиона за несколько десятков. Контейнер выбирают по тому, что программа делает с данными чаще всего.

Вектор по умолчанию

Начинайте с std::vector. Он хранит элементы подряд, в порядке добавления, допускает повторы и даёт доступ по индексу. Добавление в конец и обход у него быстрые. Медленно только искать значение: время поиска растёт вместе с размером.

Если ключи — числа подряд от 0, вектор заменяет и std::map: индекс работает как ключ. Например, счётчики оценок от 0 до 5 помещаются в std::vector<int> из шести элементов.

Ключи и поиск

std::map и std::set подходят, когда ключи уникальны и нужен их порядок. Чтобы держать вектор упорядоченным, каждое новое значение пришлось бы вставлять в нужное место, сдвигая остальные. std::map и std::set сохраняют порядок сами при каждой вставке.

Время поиска в них растёт очень медленно: удвоение размера добавляет одно-два сравнения. std::set помнит, какие значения уже встречались, а std::map хранит данные по ключу, например счётчики.

Если порядок ключей не нужен, а искать приходится часто, берите std::unordered_map. В среднем он находит ключ за одно и то же время при любом размере. Ключом может быть число или std::string: хеш для них уже определён.

ЗадачаКонтейнер
хранить по порядку, обращаться по индексуstd::vector
помнить уникальные значенияstd::set
хранить значения по ключу, ключи по порядкуstd::map
хранить значения по ключу, порядок не важенstd::unordered_map

Частая ошибка

Ключи std::unordered_map выводят, ожидая порядка по алфавиту:

C++
std::unordered_map<std::string, int> stock{  // ✗
    {"pear", 2}, {"apple", 7}, {"kiwi", 5}};
for (const auto& item : stock) {
    std::cout << item.first << ' ';
}

Порядок обхода std::unordered_map стандарт не задаёт: он зависит от реализации и может меняться после новых вставок. Если ключи нужны по порядку, возьмите std::map: его цикл выведет apple kiwi pear. Заменить нужно только тип и заголовок, остальной код останется прежним.