reserve()只改变capacity()不改变size(),故vec[0]越界崩溃;resize()才真正增加size()并初始化元素,支持下标访问。

调用 reserve() 不会让你能用 operator[] 访问新位置;调用 resize() 才会让 size() 变大、元素可访问。这是最常踩的坑,也是区分二者的核心标尺。
为什么 reserve(100) 后 vec[0] 会崩溃
因为 reserve() 只动 capacity(),不动 size()。它只是向堆申请了一块能装 100 个 int 的内存,但 vec.size() 还是 0 —— 没有构造任何对象,也没有“逻辑上存在”的元素。vec[0] 是越界访问,行为未定义,通常直接段错误或抛 std::out_of_range(取决于编译器和模式)。
常见误用场景:
- 读取网络包后想批量填充 vector,先
reserve(len)再循环写vec[i] = data[i]—— 错,必须先resize(len)或改用push_back() - 以为
reserve()等价于 C 风格的malloc(sizeof(int)*100),忘了 C++ 容器还要管对象生命周期 - 在调试时打印
capacity()很大,就误判 “空间肯定够”,结果访问失败
resize() 怎么初始化新增元素
resize(n) 会把 size() 精确设为 n。如果 n > current_size,新增部分会按类型做值初始化:
立即学习“C++免费学习笔记(深入)”;
- 内置类型(
int、double等):零初始化(0、0.0) - 类类型(如
std::string、自定义struct):调用默认构造函数 - 带第二个参数的重载
resize(n, val):用val拷贝构造每个新增元素
注意:resize(0) 会析构所有现有元素,清空容器但不一定释放内存(capacity() 通常不变)。
reserve() 真正的用途是避免 push_back 多次 realloc
当你明确知道后续要插入 N 个元素,且不关心初始值时,reserve(N) 是最优解。它让所有 push_back() 在达到 N 前都不触发内存重分配。
性能影响很实际:
- 没
reserve():插入 1000 个元素可能触发 10+ 次 realloc + 全量拷贝,时间复杂度趋近 O(N²) - 有
reserve(1000):只有一次分配,后续push_back()全是 O(1) 写入 - 但若你
reserve(1000)后只插了 10 个,就浪费了 990 个元素的内存 —— capacity 不会自动缩容,除非手动调shrink_to_fit()
什么时候该用哪个:看你要解决什么问题
判断依据不是“哪个更高级”,而是“你现在缺什么”:
- 需要立即通过下标/迭代器安全读写 N 个位置 → 用
resize(N) - 要往空容器里高效塞一批数据,且这批数据数量已知 → 先
reserve(N),再逐个push_back()或emplace_back() - 想清空内容并尽可能释放内存 →
clear()+shrink_to_fit(),不是resize(0) - 在类成员中预分配 vector 空间 → 构造函数里
reserve()比resize()更轻量,尤其对非 trivial 类型(避免无谓构造/析构)
最容易被忽略的一点:两者对迭代器的影响不同。reserve() 可能使所有迭代器失效(只要触发了重新分配);resize() 在缩小 size 时不使迭代器失效,但扩容时同样可能失效——别依赖迭代器跨 resize/reserve 调用存活。


















