std::vector<T,Allocator>::reserve
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 起)
|
返回值
(无)
异常
- 在 new_cap > max_size() 时抛出 std::length_error。
- 任何
Allocator::allocate()
会抛出的异常(典型为 std::bad_alloc)
如果抛出异常,那么此函数无效果(强异常保证)。
如果 |
(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)
|
需要 |
参阅
返回当前存储空间能够容纳的元素数 (公开成员函数) | |
返回可容纳的最大元素数 (公开成员函数) | |
改变容器中可存储元素的个数 (公开成员函数) | |
通过释放未使用的内存减少内存的使用 (公开成员函数) |