std::vector<T,Allocator>::reserve
void reserve( size_type new_cap ); |
(до C++20) | |
constexpr void reserve( size_type new_cap ); |
(с 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).
Если брошено исключение, функция не имеет эффекта (сильная гарантия исключений).
|
Если перемещающий конструктор |
(с C++11) |
Сложность
Максимум линейная по size() контейнера.
Примечания
Правильное использование reserve() может предотвратить ненужные перераспределения, но ненадлежащее использование reserve() (например, вызов перед каждым вызовом push_back()) может фактически увеличить количество перераспределений (заставляя емкость расти линейно, а не экспоненциально) и привести к увеличению вычислительной сложности и снижению производительности. Например, функция, которая получает произвольный вектор по ссылке и добавляет в него элементы, обычно не должна вызывать reserve() для вектора, так как она не знает особенностей использования вектора.
При вставке диапазона версия insert() для диапазона обычно предпочтительнее, так как она сохраняет правильное поведение роста емкости, в отличие от reserve() в сочетании с рядом вызовов push_back().
reserve() не может использоваться для уменьшения емкости контейнера; для этой цели предоставляется shrink_to_fit().
Пример
#include <cstddef>
#include <iostream>
#include <new>
#include <vector>
// minimal C++11 allocator with debug output
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); // reserves at least max_elements * sizeof(int) bytes
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 | Применяется к | Поведение, опубликованное | Правильное поведение |
|---|---|---|---|
| LWG 329 | C++98 | перераспределение может быть вызвано, если вставка делает размер вектора больше размера, указанного в последнем вызове reserve() |
вызывается только если размер вектора становится больше capacity() |
| LWG 2033 | C++11 | T не было необходимо требовать MoveInsertable |
требование выполняется |
См. также
| возвращает количество элементов, которое может храниться в текущем выделенном хранилище (публичный член-функция) |
|
| возвращает максимальное возможное количество элементов (публичный член-функция) |
|
| изменяет количество хранимых элементов (публичный член-функция) |
|
|
(DR*) |
уменьшает использование памяти, освобождая неиспользуемую память (публичный член-функция) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/container/vector/reserve