std::vector<T,Allocator>::reserve
void reserve( size_type new_cap ); |
(C++20 起为 constexpr) |
|
增加 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 <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 << "在 " << 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)
|
需要 |
参阅
| 返回当前存储空间能够容纳的元素数 (公开成员函数) | |
| 返回可容纳的最大元素数 (公开成员函数) | |
| 改变存储元素的个数 (公开成员函数) | |
(DR*) |
通过释放未使用的内存减少内存的使用 (公开成员函数) |