vector 初始化和容量预估至关重要,未预分配空间导致频繁重分配与拷贝;reserve 只改容量不影响大小,resize 才改大小;迭代器在重分配后必然失效;移动语义可避免深拷贝;operator[] 无检查但高效,at() 有检查但开销大。

vector 初始化和容量预估很关键
不预分配空间就反复 push_back,会导致多次内存重分配和元素拷贝,尤其存大对象时性能掉得明显。默认构造的 vector 容量是 0,第一次插入就触发分配;后续扩容通常是 1.5 倍或 2 倍增长,旧数据全要 memcpy。
- 知道大概元素数量?直接用
vector<int> v(n)</int>或vector<int> v; v.reserve(n)</int> - 初始化后又清空再复用?记得调
v.clear()不会释放内存,要缩容得写vector<int>(v).swap(v)</int>(C++11 后更推荐v.shrink_to_fit(),但不保证一定生效) -
reserve只影响容量(capacity()),不影响大小(size());resize才会真正改变size()并可能初始化新元素
迭代器失效是高频崩溃源头
只要 vector 内存重分配(比如 push_back 触发扩容、insert / erase 改变布局),所有指向该 vector 的迭代器、指针、引用立刻失效。不是“可能出错”,是“必然未定义行为”——调试时看着正常,发布后随机崩。
- 避免在循环中边遍历边
push_back或erase:先收集索引或用erase-remove惯用法(v.erase(remove_if(v.begin(), v.end(), pred), v.end())) - 用下标访问(
v[i])比迭代器更抗干扰,但注意不检查越界;真要迭代,确保操作不触发重分配,或把修改逻辑拆到遍历之后 -
data()返回的指针在任何修改容器的操作后都可能失效,别缓存它
移动语义能省掉大量拷贝
C++11 起,vector 支持移动构造和移动赋值。传参、返回、swap 时优先用右值引用,避免深拷贝整个底层数组。尤其函数返回局部 vector 时,编译器通常能自动移动(RVO),但显式写 std::move(v) 在某些场景仍有必要。
- 函数返回:直接
return vector<int>{1,2,3};</int>,不用std::move;但若返回命名变量(如vector<int> v = ...; return v;</int>),加std::move(v)更稳妥 - 接收参数:想接管所有权就用
void f(vector<int>&& v)</int>,否则用 const 引用const vector<int>& v</int> - 注意:移动后原 vector 处于有效但未指定状态,只能安全调用
size()、empty()或赋值,不能再用operator[]或迭代器
用 at() 还是 operator[]?看场景
operator[] 不检查下标,快但危险;at() 做边界检查,越界抛 std::out_of_range,适合调试或用户输入驱动的索引。生产环境别指望靠 at() 挡住所有问题——它只查 size(),不查 capacity(),而且异常开销不小。
立即学习“C++免费学习笔记(深入)”;
- 内部循环、性能敏感路径?无条件用
operator[],但确保逻辑上绝不会越界(比如用for (size_t i = 0; i ) - 处理外部数据(文件、网络、GUI 输入)?优先
at(),或者自己加断言:assert(i - 注意
v.at(i)和v[i]对空 vector 都不合法;空 vector 的v[0]是未定义行为,v.at(0)抛异常
vector 底层就是动态数组,高效的前提是你清楚它什么时候会 realloc、什么时候迭代器会死、哪些操作暗含拷贝。很多“慢”和“崩”,其实就差一行 reserve 或一个 std::move。



















