std::vector<T,Allocator>:: reserve
|
void
reserve
(
size_type new_cap
)
;
|
(constexpr начиная с C++20) | |
Увеличивает ёмкость вектора (общее количество элементов, которое вектор может содержать без необходимости перераспределения памяти) до значения, которое больше или равно new_cap . Если new_cap больше текущей capacity() , выделяется новое хранилище, в противном случае функция ничего не делает.
reserve()
не изменяет размер вектора.
Если
new_cap
больше, чем
capacity()
, все итераторы (включая итератор
end()
) и все ссылки на элементы становятся недействительными. В противном случае никакие итераторы или ссылки не становятся недействительными.
После вызова
reserve()
вставки не будут вызывать перераспределение памяти, если только вставка не приведет к увеличению размера вектора сверх значения
capacity()
.
Содержание |
Параметры
| new_cap | - | новая вместимость вектора, в количестве элементов |
| Требования к типу | ||
-
T
должен удовлетворять требованиям
MoveInsertable
в
*
this
.
(начиная с C++11)
|
||
Возвращаемое значение
(нет)
Исключения
- std::length_error если new_cap > max_size ( ) .
-
Любое исключение, выброшенное
Allocator::allocate()(обычно std::bad_alloc ).
Если возникает исключение, эта функция не оказывает никакого эффекта ( strong exception guarantee ).
|
Если перемещающий конструктор
|
(since C++11) |
Сложность
Не более чем линейно по size() контейнера.
Примечания
Правильное использование
reserve()
может предотвратить ненужные перераспределения памяти, однако некорректное применение
reserve()
(например, вызов перед каждым
push_back()
) может фактически увеличить количество перераспределений (вызывая линейный рост вместимости вместо экспоненциального) и привести к увеличению вычислительной сложности и снижению производительности. Например, функция, получающая произвольный вектор по ссылке и добавляющая к нему элементы, обычно
не должна
вызывать
reserve()
для этого вектора, поскольку ей неизвестны характеристики использования вектора.
При вставке диапазона версия
insert()
для диапазонов обычно предпочтительнее, так как она сохраняет корректное поведение увеличения ёмкости, в отличие от
reserve()
с последующей серией вызовов
push_back()
.
reserve()
не может использоваться для уменьшения вместимости контейнера; для этой цели предусмотрен метод
shrink_to_fit()
.
Пример
#include <cstddef> #include <iostream> #include <new> #include <vector> // минимальный C++11 аллокатор с отладочным выводом template<class Tp> struct NAlloc { typedef Tp value_type; NAlloc() = default; template<class T> NAlloc(const NAlloc<T>&) {} Tp* allocate(std::size_t n) { n *= sizeof(Tp); Tp* p = static_cast<Tp*>(::operator new(n)); std::cout << "allocating " << n << " bytes @ " << p << '\n'; return p; } void deallocate(Tp* p, std::size_t n) { std::cout << "deallocating " << n * sizeof *p << " bytes @ " << p << "\n\n"; ::operator delete(p); } }; template<class T, class U> bool operator==(const NAlloc<T>&, const NAlloc<U>&) { return true; } template<class T, class U> bool operator!=(const NAlloc<T>&, const NAlloc<U>&) { return false; } int main() { constexpr int max_elements = 32; std::cout << "using reserve: \n"; { std::vector<int, NAlloc<int>> v1; v1.reserve(max_elements); // резервирует как минимум max_elements * sizeof(int) байт for (int n = 0; n < max_elements; ++n) v1.push_back(n); } std::cout << "not using reserve: \n"; { std::vector<int, NAlloc<int>> v1; for (int n = 0; n < max_elements; ++n) { if (v1.size() == v1.capacity()) std::cout << "size() == capacity() == " << v1.size() << '\n'; v1.push_back(n); } } }
Возможный вывод:
using reserve: allocating 128 bytes @ 0xa6f840 deallocating 128 bytes @ 0xa6f840 not using reserve: size() == capacity() == 0 allocating 4 bytes @ 0xa6f840 size() == capacity() == 1 allocating 8 bytes @ 0xa6f860 deallocating 4 bytes @ 0xa6f840 size() == capacity() == 2 allocating 16 bytes @ 0xa6f840 deallocating 8 bytes @ 0xa6f860 size() == capacity() == 4 allocating 32 bytes @ 0xa6f880 deallocating 16 bytes @ 0xa6f840 size() == capacity() == 8 allocating 64 bytes @ 0xa6f8b0 deallocating 32 bytes @ 0xa6f880 size() == capacity() == 16 allocating 128 bytes @ 0xa6f900 deallocating 64 bytes @ 0xa6f8b0 deallocating 128 bytes @ 0xa6f900
Отчеты о дефектах
Следующие отчеты об изменениях в поведении, содержащие описания дефектов, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| LWG 329 | C++98 |
перераспределение памяти могло быть вызвано, если вставка
делает размер вектора больше, чем размер, указанный в последнем вызове
reserve()
|
вызывается только если размер
вектора становится больше, чем capacity() |
| LWG 2033 | C++11 |
T
не требовалось быть
MoveInsertable
|
требуется |
Смотрите также
|
возвращает количество элементов, которое может содержаться в выделенной в данный момент памяти
(public member function) |
|
|
возвращает максимально возможное количество элементов
(public member function) |
|
|
изменяет количество хранимых элементов
(public member function) |
|
|
(
DR*
)
|
уменьшает использование памяти за счет освобождения неиспользуемой памяти
(public member function) |