resize 改变 size 并构造/析构元素,reserve 仅预分配内存、影响 capacity 但不改变 size;误用 reserve 后直接访问未初始化元素将越界崩溃。

resize 会改变 size,reserve 只影响 capacity
resize 修改的是 vector 的逻辑长度(即 size()),它会实际构造或析构元素;reserve 只预分配内存,只影响 capacity(),不碰现有元素,也不改变 size()。
常见错误是以为 reserve(100) 后就能直接访问 v[50] —— 实际会越界崩溃,因为 size() 还是 0。真正要“填满”空间,得用 resize(100) 或配合 push_back/emplace_back。
-
resize(n):若n > size(),默认构造n - size()个元素;若n ,销毁末尾多余元素 -
reserve(n):仅当n > capacity()时才重新分配内存;若已够用,什么也不做 - 调用
reserve后插入大量元素(如循环push_back),可避免多次 realloc + memcpy
频繁 push_back 时不 reserve 就容易触发多次扩容
标准库中 vector 扩容通常是按 1.5× 或 2× 增长(具体实现依赖编译器,如 libstdc++ 用 1.5,MSVC 用 2),每次扩容都要 malloc 新内存、memcpy 老数据、delete 旧内存——对大对象或高频插入场景,开销明显。
比如循环插入 1000 个 std::string,没 reserve 可能触发 10+ 次内存重分配;提前 reserve(1000),就只有一次预分配。
立即学习“C++免费学习笔记(深入)”;
- 实测:含深拷贝成员的类对象,扩容成本可能比构造本身还高
-
reserve不保证“恰好”分配 n 个元素空间,底层可能向上取整到内存页边界 - 过度
reserve(如预估 10 万却reserve(1000000))会浪费内存,尤其在嵌入式或内存敏感场景
resize 默认初始化 vs reserve + emplace_back 的性能差异
如果目标是填充一堆非默认可构造的对象(比如 vector<:thread>),用 resize 会失败(std::thread 无默认构造函数);此时必须先 reserve,再逐个 emplace_back。
即使类型支持默认构造,resize 也会先默认构造所有元素,再挨个赋值——相当于做了两遍构造;而 reserve + emplace_back 是“边建边填”,更符合意图且通常更快。
-
resize(n, value)适合需要统一初值的场景(如全设为 -1 的计数数组) - 对自定义类型,
resize调用默认构造函数,emplace_back(args...)调用对应构造函数,语义和开销都不同 - 注意:
emplace_back在 capacity 不足时仍会触发扩容,所以reserve是前置条件,不是可选项
capacity 为 0 时的特殊行为与调试技巧
刚创建的空 vector,capacity() 可能为 0(如 GCC 13+ 的 debug mode)或非零(如 release 下常见为 0 或 1)。这会影响你对 reserve 是否真正触发分配的判断。
调试时别只看 size(),务必检查 capacity();用 std::cout 快速验证策略是否生效。另外,shrink_to_fit() 是唯一能主动减小 capacity 的方法,但它只是请求,不保证成功。
- 移动语义后,源
vector的capacity可能被清零或保留,取决于实现 - 用
std::vector是 C++11 前强制释放内存的惯用法,现在推荐().swap(v) v.clear(); v.shrink_to_fit(); - ASan/UBSan 下,访问
capacity()之外的内存不会报错,但越界读写size()之外会触发诊断











