必须在首次插入前调用reserve(),因为一旦push_back触发扩容,vector已发生搬迁,后续reserve无法撤销;它仅预防未来搬迁,不改变size,也不初始化元素。

提前调用 reserve() 是唯一可靠方式,且必须在首次插入前完成
为什么必须在 push_back 之前调用 reserve
一旦 push_back() 触发过扩容,vector 就已经发生过至少一次“搬迁”;后续再调用 reserve() 只能防止进一步搬迁,无法撤销已发生的拷贝。很多开发者误以为“边插边 reserve”能补救,实际无效。
-
reserve(n)只影响 capacity,不改变 size —— 它不做任何元素初始化,也不移动已有数据(除非新容量 > 当前 capacity) - 如果 vector 已经扩容过 3 次,capacity 从 1→2→4→8,此时调用
reserve(100)会再搬一次;但若一开始就reserve(100),就完全避开这 4 次搬迁 - 编译器不会帮你推断“你接下来要插多少个”,它只按当前操作响应
reserve 参数取值:宁略高、勿略低
预留空间不足仍会触发扩容。比如你知道大概要存 95 个元素,但只 reserve(90),第 91 次 push_back() 就又得搬一次家。
- 保守做法:用预估最大值,如
reserve(expected_max + 5) - 若上限明确(例如读固定大小的文件),直接用精确值:
reserve(file_size / sizeof(int)) - 避免用
reserve(vec.size() + 10)这类动态计算——此时 size 已非零,说明搬迁可能已发生
常见误用场景:resize 和 reserve 混淆
resize() 看起来像预分配,但它本质是“改 size + 初始化”,不是为后续 push_back() 防搬迁设计的。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
立即学习“C++免费学习笔记(深入)”;
-
v.resize(100)→ size=100, capacity≥100,但所有元素已被默认构造(比如int变成 0),你再push_back()就是在第 101 位插,仍可能触发扩容 -
v.reserve(100)→ size=0, capacity=100,干净等待你逐个push_back(),全程零搬迁 - 真正需要初始化时,用
vector<int> v(100, 0)</int>构造,而非靠resize()补救
验证是否真的避开了搬迁
别只信逻辑,用 capacity() 和地址观察来确认:
- 插入前打印
v.capacity(),插入后再次打印,值不变才说明没搬迁 - 对指针敏感场景(如保存迭代器或元素地址),可记录
&v[0],插入若干元素后再比对地址是否变化 - 注意:
clear()不释放内存,shrink_to_fit()是请求释放,不保证成功,二者都不解决“预防搬迁”问题
最易被忽略的一点:reserve 的效果完全依赖于你对数据规模的预判是否落在第一次插入之前——它不是兜底机制,而是前置契约。一旦错过那个时间点,搬迁就已成事实。

















