Проблемы - Множественные реалокации при последовательных push_back — накладные копирования/перемещения и потеря производительности (хотя амортизированная сложность O(1), будут редкие O(n)-реалокации). - Пиковое потребление памяти: в процессе роста vector выделит память примерно до ёмкости ≥ 100000010000001000000 элементов (интегрально), что может быть значительным. - После вызова resize(100100100) ёмкость (capacity) остаётся большой — память не возвращается ОС, т.е. вектор займёт больше памяти, чем реально нужно. - При реалокации все указатели/итераторы/ссылки на элементы инвалидируются. - Возможен выброс std::bad_alloc при нехватке памяти. Как избежать (кратко, с примерами) 1. Если заранее известен максимальный размер — зарезервировать: - v.reserve(100000010000001000000); // избегает реалокаций при заполнении 2. Если вам на самом деле нужны только первые 100100100 элементов — не заполняйте миллион: - v.reserve(100100100); for (int i=0; i<100100100; ++i) v.push_back(i); - или сразу v.resize(100100100); и заполнять v[i]. 3. Быстрая инициализация без push_back-роста: - v.resize(100000010000001000000); for (int i=0; i<100000010000001000000; ++i) v[i] = i; // избегает копирований при росте 4. Освобождение лишней памяти после shrink: - v.resize(100100100); v.shrink_to_fit(); // но shrink_to_fit не гарантирует освобождение - Гарантированный способ: vector(v.begin(), v.begin()+100100100).swap(v); // новая контейнерная ёмкость = 100100100
5. Учитывайте инвалидизацию итераторов — не храните долгоживущие указатели на элементы через период возможных реалокаций. Выбор стратегии зависит от задачи: если нужно временно построить большой буфер — reserve или resize + заполнение; если большие данные не нужны — не создавать их вообще; если нужно вернуть память — использовать swap-трюк для надёжного уменьшения capacity.
- Множественные реалокации при последовательных push_back — накладные копирования/перемещения и потеря производительности (хотя амортизированная сложность O(1), будут редкие O(n)-реалокации).
- Пиковое потребление памяти: в процессе роста vector выделит память примерно до ёмкости ≥ 100000010000001000000 элементов (интегрально), что может быть значительным.
- После вызова resize(100100100) ёмкость (capacity) остаётся большой — память не возвращается ОС, т.е. вектор займёт больше памяти, чем реально нужно.
- При реалокации все указатели/итераторы/ссылки на элементы инвалидируются.
- Возможен выброс std::bad_alloc при нехватке памяти.
Как избежать (кратко, с примерами)
1. Если заранее известен максимальный размер — зарезервировать:
- v.reserve(100000010000001000000); // избегает реалокаций при заполнении
2. Если вам на самом деле нужны только первые 100100100 элементов — не заполняйте миллион:
- v.reserve(100100100); for (int i=0; i<100100100; ++i) v.push_back(i);
- или сразу v.resize(100100100); и заполнять v[i].
3. Быстрая инициализация без push_back-роста:
- v.resize(100000010000001000000); for (int i=0; i<100000010000001000000; ++i) v[i] = i; // избегает копирований при росте
4. Освобождение лишней памяти после shrink:
- v.resize(100100100); v.shrink_to_fit(); // но shrink_to_fit не гарантирует освобождение
- Гарантированный способ: vector(v.begin(), v.begin()+100100100).swap(v); // новая контейнерная ёмкость = 100100100 5. Учитывайте инвалидизацию итераторов — не храните долгоживущие указатели на элементы через период возможных реалокаций.
Выбор стратегии зависит от задачи: если нужно временно построить большой буфер — reserve или resize + заполнение; если большие данные не нужны — не создавать их вообще; если нужно вернуть память — использовать swap-трюк для надёжного уменьшения capacity.