reserve不改变size只提升capacity,预分配内存但不构造元素;需用resize或push_back填充,避免越界访问。

reserve 不改变 size,只影响 capacity
reserve 的作用是提前为 std::vector 的内部缓冲区申请足够内存,但它**不会构造任何元素**,也不会改变 vector::size()。调用后 size() 仍为 0(或原有值),但 capacity() 至少达到你指定的数值。
常见误用是以为 reserve(n) 后就能直接访问 v[0] 到 v[n-1] —— 这会越界,因为这些位置还没被构造。真正要“占位”,得用 resize(n) 或配合 push_back。
- 只预分配:用
reserve,后续靠push_back增长 - 需要默认初始化元素:用
resize(n) - 既要空间又要自定义初值:用
resize(n, value)
为什么多次 push_back 会慢?看扩容机制
当 vector 容量不足时,push_back 触发扩容:分配新内存 → 逐个移动/拷贝旧元素 → 释放旧内存。移动成本取决于元素类型(如含深拷贝的类开销大),且每次扩容通常按 1.5× 或 2× 增长,导致早期频繁小扩容(比如从 1→2→4→8…)。
假设你要塞 1000 个 std::String,不 reserve 可能触发 10+ 次重新分配;而 v.reserve(1000) 后,所有 push_back 都在原内存完成,零移动。
立即学习“C++免费学习笔记(深入)”;
注意:reserve 本身也有开销(一次 malloc + 构造预留空间的元数据),但它是一次性成本,远小于多次 realloc + copy 的叠加。
reserve 的实际使用时机和坑
最值得用 reserve 的场景,是你**明确知道最终元素数量**,且会连续插入(如读文件、解析数组、批量生成)。
- ✅ 推荐:读取 N 行文本前
v.reserve(N),再循环push_back(line) - ✅ 推荐:计算出结果数量后,先
reserve再填充(比如图算法中预估邻接表大小) - ❌ 不推荐:循环中每次
reserve(i)—— 这反而引发更多分配 - ⚠️ 注意:
reserve(0)不释放内存(c++11 起标准不保证),想缩容得用shrink_to_fit(),但它是非强制的 - ⚠️ 注意:对小对象(如
int)优化效果可能被编译器内联/向量化掩盖,但对非 POD 类型(如std::vector<:string>)收益显著
对比 resize 和 reserve 的行为差异
这是最容易混淆的点。resize(n) 会让 size() == n,并确保前 n 个元素存在(默认构造或按值填充);reserve(n) 只保证 capacity() >= n,size() 完全不变。
示例:
std::vector v; v.reserve(10); // capacity ≥ 10, size == 0 v.push_back("hello"); // OK,现在 size == 1,仍在预留空间内 // v[5] = "world"; // ❌ 越界!v.size() 是 1,不是 10 v.resize(10, "default"); // 现在 size == 10,capacity ≥ 10,v[5] 可写
如果你只是要填满一个已知大小的容器,resize 更直接;如果你要高效追加、且初始为空,reserve + push_back 是更轻量的选择。
真正关键的不是“该不该用”,而是理解 size 和 capacity 的分离设计 —— 这个分离正是 reserve 存在的理由,也是它容易被误用的根源。