Ответ
Основная проблема — множественные реаллокации, которые приводят к падению производительности.
Механизм работы std::vector:
- Вектор хранит элементы в непрерывном блоке памяти.
- У него есть два размера:
size()(количество элементов) иcapacity()(размер выделенного блока памяти). - При
push_back(), еслиsize() == capacity(), происходит реаллокация: выделяется новый, больший блок памяти (обычно в 1.5 или 2 раза больше), все существующие элементы копируются или перемещаются в него, старый блок освобождается.
Пример с проблемой:
std::vector<int> vec; // capacity = 0
for (int i = 0; i < 100; ++i) {
vec.push_back(i); // Реаллокации произойдут при i = 0, 1, 2, 4, 8, 16, 32, 64...
}
// Каждая реаллокация — это O(N) операций копирования/перемещения.
Решение — метод reserve():
std::vector<int> vec;
vec.reserve(100); // Однократное выделение памяти под 100 элементов
for (int i = 0; i < 100; ++i) {
vec.push_back(i); // Ни одной реаллокации. Вставка за O(1).
}
Дополнительные соображения:
- Использование
emplace_back()вместоpush_back()позволяет конструировать объекты прямо в памяти вектора, избегая лишних копирований. - Если конечный размер известен, можно использовать конструктор или
assign().// Альтернатива: инициализация из итераторов или списка std::vector<int> vec(100); // 100 элементов, инициализированных нулями // или std::vector<int> vec; vec.assign(100, 0); // 100 нулей