vector扩容按倍数一次性分配内存,倍数因标准库而异(GCC/Clang约2.0倍,MSVC约1.5倍),触发条件为size()==capacity(),扩容导致所有迭代器、引用、指针失效,reserve()可预分配避免运行时扩容。

vector 扩容不是“加一个元素就分配一次内存”,而是按倍数一次性多分,但具体倍数不统一,且每次扩容都会让所有迭代器、引用、指针失效。
扩容触发条件:size() == capacity()
只有当 push_back 或 insert 等操作导致当前元素数量超过已分配容量时,才会触发扩容。此时 vector 必须:
- 申请一块更大的连续内存(新容量 > 旧 capacity)
- 将旧元素逐个移动或拷贝到新内存(调用移动构造或拷贝构造)
- 析构旧内存中的对象
- 释放旧内存
这个过程是原子的,但耗时与当前 size() 成正比。小容器可能感觉不到,百万级元素扩容一次可能卡住几毫秒。
不同标准库的倍增因子差异
标准没规定具体增长比例,但主流实现有事实惯例:
立即学习“C++免费学习笔记(深入)”;
- GCC(libstdc++)和 Clang(libc++):接近
2.0倍(例如从 1→2→4→8…) - MSVC(MS STL):约
1.5倍(例如从 1→2→3→4→6→9…)
为什么不用 1.0 + 1?那样每插入一个元素都扩容,均摊复杂度会退化成 O(n)。而倍增策略能保证 push_back 的均摊时间复杂度为 O(1)——前提是移动/拷贝本身是 O(1)。
reserve() 是唯一可控的扩容干预手段
reserve() 只改 capacity(),不改变 size(),也不会构造任何元素。它常用于:
- 已知最终规模(如读取文件前预估行数)
- 避免循环中反复扩容(尤其配合
emplace_back) - 减少内存碎片(一次分配到位,比多次小分配更紧凑)
注意:reserve(n) 不保证 capacity() == n,只保证 capacity() >= n;若当前 capacity() >= n,则什么也不做。
迭代器失效是扩容最隐蔽的代价
只要发生扩容,begin()、end()、所有中间迭代器、&v[i] 返回的指针、对元素的引用(auto& x = v[0])全部失效。常见错误包括:
- 边遍历边
push_back(循环中修改自身 size 导致迭代器悬空) - 保存了
v.data()后又扩容,再用该指针访问 - 把
vector传值给函数,函数内扩容,返回后原变量迭代器仍失效(因传值复制的是新缓冲区,不影响原对象,但你可能误以为“没动原 vector”)
真正安全的做法是:扩容前确保没有活跃的迭代器/引用/指针指向其元素;或者改用 reserve() 预分配,彻底避开运行时扩容。


















