C++MiddleTechnical
Что такое STL? Назовите ключевые контейнеры и их характеристики производительности.
STL — контейнеры, алгоритмы и итераторы стандартной библиотеки. vector (O(1) random access, лучшая кэш-локальность) — выбор по умолчанию; unordered_map (O(1) lookup) — для частых поисков; map (O(log n), упорядоченный) — когда нужен порядок ключей.
Что такое STL
STL (Standard Template Library) — часть стандартной библиотеки C++, содержащая обобщённые контейнеры, алгоритмы и итераторы. Все алгоритмы работают через итераторы и не зависят от конкретного контейнера.
Последовательные контейнеры
- std::vector<T> — динамический массив. Random access O(1). push_back амортизированно O(1). Вставка/удаление в середину O(n). Лучшая кэш-локальность.
- std::deque<T> — двусторонняя очередь. push_front/push_back O(1). Random access O(1), но хуже кэш-локальность (блоки памяти).
- std::list<T> — двусвязный список. Вставка/удаление O(1) при наличии итератора. Нет random access. Плохая кэш-локальность — в реальных задачах часто медленнее vector даже для вставки.
- std::array<T, N> — массив фиксированного размера на стеке. Zero overhead, random access O(1).
Ассоциативные контейнеры (упорядоченные)
- std::map<K, V> — красно-чёрное дерево, ключи отсортированы. Insert/find/erase O(log n). Требует
operator<. - std::set<K> — то же, без значений. O(log n) операции.
- std::multimap / std::multiset — допускают дубликаты ключей.
Хеш-контейнеры (C++11)
- std::unordered_map<K, V> — хеш-таблица. Амортизированно O(1) insert/find/erase. Worst case O(n) при коллизиях. Требует
std::hash<K>. - std::unordered_set<K> — то же, без значений.
Адаптеры
- std::stack — обёртка над deque (или vector). LIFO.
- std::queue — обёртка над deque. FIFO.
- std::priority_queue — бинарная куча (max-heap по умолчанию). push O(log n), top/pop O(log n).
#include <vector>
#include <unordered_map>
#include <map>
#include <set>
#include <algorithm>
#include <iostream>
int main() {
// vector — рабочая лошадь
std::vector<int> v = {5, 3, 1, 4, 2};
std::sort(v.begin(), v.end()); // O(n log n)
v.push_back(6); // амортизированно O(1)
v.insert(v.begin() + 2, 99); // O(n) — сдвигает элементы
// reserve — избегаем реаллокаций
std::vector<int> big;
big.reserve(1'000'000); // одно выделение памяти
// unordered_map — O(1) lookup
std::unordered_map<std::string, int> freq;
for (const auto& word : {"a", "b", "a", "c", "b", "a"}) {
freq[word]++;
}
// freq["a"] == 3
// map — если нужен порядок ключей
std::map<int, std::string> ordered;
ordered[3] = "three";
ordered[1] = "one";
ordered[2] = "two";
for (const auto& [k, v2] : ordered) {
std::cout << k << " " << v2 << '\n'; // 1, 2, 3
}
// set — уникальные элементы, отсортированы
std::set<int> s = {5, 3, 1, 3, 5};
// s == {1, 3, 5}
// lower_bound — бинарный поиск в map/set O(log n)
auto it = ordered.lower_bound(2);
std::cout << it->first << '\n'; // 2
}
Подводные камни
- vector vs list: list проигрывает vector по скорости вставки в середину на реальных данных из-за плохой кэш-локальности — L1/L2 промахи дороже, чем O(n) сдвиг в vector.
- Инвалидация итераторов vector: любая операция, вызывающая реаллокацию (push_back без reserve), инвалидирует все итераторы, указатели и ссылки.
- unordered_map порядок не гарантирован: итерация даёт произвольный порядок; не полагайтесь на него в тестах.
- std::map operator[]:
map[key]создаёт элемент с нулевым значением, если ключа нет — используйтеfind()илиcount()для проверки без вставки. - Хеш-коллизии: при атаке на хеш (DoS) unordered_map деградирует до O(n) — используйте рандомизированный seed или robin-hood hashing в продакшне.
- reserve для unordered_map: без
reserveтаблица перехеширует данные при заполнении — для известного числа элементов вызовитеm.reserve(n)заранее. - emplace vs insert/push_back:
emplace_backконструирует элемент на месте, insert — создаёт временный объект; для нетривиальных типов разница ощутима.
Common mistakes
- Объяснять STL контейнеры и сложность только по синтаксису, без жизненного цикла и стоимости.
- Игнорировать ошибки, null/empty состояния, порядок инициализации или режим сборки.
- Давать пример, который работает в демо, но ломается при изменении владельца ресурса.
- Показывать сырой указатель без объяснения владельца и момента освобождения.
What the interviewer is testing
- Кандидат формулирует точную модель для STL контейнеры и сложность, а не только определение.
- Пример компилируем, безопасен по lifetime и соответствует версии технологии.
- Названы trade-off, ограничения и диагностируемые симптомы ошибки.