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

来自cppreference.com
< cpp‎ | container‎ | vector
 
 
 
 
void reserve( size_type new_cap );
(C++20 前)
constexpr void reserve( size_type new_cap );
(C++20 起)

增加 vector 的容量(即 vector 在不重新分配存储的情况下能最多能持有的元素的数量)到大于或等于 new_cap 的值。如果 new_cap 大于当前的 capacity(),那么就会分配新存储,否则该方法不做任何事。

reserve() 不会更改 vector 的大小。

如果 new_cap 大于 capacity(),那么所有迭代器,包含 end() 迭代器和所有到元素的引用都会失效。否则,没有迭代器或引用会失效。

在调用 reserve() 后,插入只会在它将导致 vector 的大小大于 capacity() 的值时触发重新分配。

参数

new_cap - vector 的新容量
类型要求
-
T 必须符合可移动插入 (MoveInsertable) *this 中的要求。(C++11 起)

返回值

(无)

异常

如果抛出异常,那么此函数无效果(强异常保证)。

如果 T 的移动构造函数不是 noexcept 的且 T可复制插入 (CopyInsertable) *this,那么 vector 将使用移动构造函数。如果它抛出异常,那么摒弃保证,且效果未指定。

(C++11 起)

复杂度

最多与容器的 size() 成线性。

注解

正确使用 reserve() 能避免不必要的分配,但不适当地使用 reserve()(例如在每次 push_back() 调用前调用它)可能会实际增加重分配的数量(通过导致容量线性而非指数增长)并导致计算复杂度增加,性能下降。例如,按引用接受任意 vector 并后附元素的函数通常应在 vector 上调用 reserve() ,因为它不知道该 vector 的使用特征。

插入范围时,insert() 的范围版本通常更合适,因为它保持正确的容量增长行为,而与 reserve() 后随一系列 push_back() 不同。

不能用 reserve() 减少容器容量。为该目的提供的是 shrink_to_fit()

示例

#include <cstddef>
#include <new>
#include <vector>
#include <iostream>
 
// 带调试输出的最小 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 << "在 " << p << " 分配 " << n << " 个字节\n";
        return p;
    }
 
    void deallocate(Tp* p, std::size_t n)
    {
        std::cout << "在 " << p << "解分配 " << n * sizeof *p << " 个字节\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 << "使用 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 << "不使用 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);
        }
    }
}

可能的输出:

使用 reserve:
在 0xa6f840 分配 128 个字节
在 0xa6f840 解分配 128 个字节
 
不使用 reserve:
size() == capacity() == 0
在 0xa6f840 分配 4 个字节
 
size() == capacity() == 1
在 0xa6f860 分配 8 个字节
在 0xa6f840 解分配 4 个字节
 
size() == capacity() == 2
在 0xa6f840 分配 16 个字节
在 0xa6f860 解分配 8 个字节
 
size() == capacity() == 4
在 0xa6f880 分配 32 个字节
在 0xa6f840 解分配 16 个字节
 
size() == capacity() == 8
在 0xa6f8b0 分配 64 个字节
在 0xa6f880 解分配 32 个字节
 
size() == capacity() == 16
在 0xa6f900 分配 128 个字节
在 0xa6f8b0 解分配 64 个字节
 
在 0xa6f900 解分配 128 个字节

缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 出版时的行为 正确行为
LWG 329 C++98 插入操作使 vector 的大小超过向上一次
reserve() 调用提供的大小时可能会重分配
只有在大小超过
capacity() 时才会重分配
LWG 2033 C++11 T 不需要可移动插入 (MoveInsertable) 需要

参阅

返回当前存储空间能够容纳的元素数
(公开成员函数)
返回可容纳的最大元素数
(公开成员函数)
改变容器中可存储元素的个数
(公开成员函数)
通过释放未使用的内存减少内存的使用
(公开成员函数)