Namespaces
Variants

std::vector<T,Allocator>:: reserve

From cppreference.net
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)

Возвращаемое значение

(нет)

Исключения

Если возникает исключение, эта функция не оказывает никакого эффекта ( strong exception guarantee ).

Если перемещающий конструктор T не является noexcept и T не является CopyInsertable в * this , vector будет использовать выбрасывающий перемещающий конструктор. Если он выбрасывает исключение, гарантии снимаются и эффекты не определены.

(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)
уменьшает использование памяти за счет освобождения неиспользуемой памяти
(public member function)