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).
Если выбрасывается исключение, эта функция не оказывает никакого эффекта (сильная гарантия безопасности при исключениях).
| Если конструктор перемещения | (с 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/cpp/container/vector/reserve