
vector 是什么,什么时候该用它
vector 是 C++ 标准库中封装动态数组的容器,底层是连续内存块,支持随机访问、尾部高效插入/删除,但中间插入或删除代价高(需移动后续元素)。它适合需要「动态大小 + 快速索引 + 尾部频繁增删」的场景,比如读取不确定数量的输入、临时缓存计算结果、作为函数返回的集合等。
别把它当链表用——insert 或 erase 在非尾部位置会触发大量拷贝;也别默认认为它“比原生数组慢很多”——现代编译器对 std::vector 优化充分,且 operator[] 和 at() 都是 O(1);更别在性能敏感循环里反复调用 size() 而不缓存——某些 debug 模式下 size() 不是纯内联。
初始化和容量控制的关键细节
vector 的构造方式直接影响内存分配行为。默认构造 std::vector 不分配堆内存;带初始大小的 std::vector 会分配并默认初始化 10 个 int(值为 0);而 std::vector 初始化为 10 个 42。
-
reserve(n)只改变容量(capacity),不改变大小(size),也不构造元素——适合预知大致规模时避免多次扩容 -
resize(n)改变 size,若 n > 当前 size,则追加默认构造元素;若 n -
shrink_to_fit()是非强制请求,仅建议释放多余容量,实际是否释放由实现决定(GCC libstdc++ 通常响应,MSVC 有时忽略)
std::vector v; v.reserve(1000); // 分配够 1000 个 string 的空间,但 v.size() == 0 v.push_back("hello"); // 此时 v.size() == 1,v.capacity() >= 1000 v.resize(5); // v.size() == 5,新增 4 个空字符串 ""
迭代器失效的典型场景和规避方法
vector 迭代器失效不是“偶尔出错”,而是有明确规则:任何导致重新分配内存的操作(如 push_back、insert、resize 等在 size 超过 capacity 时)会让所有指向该 vector 的迭代器、指针、引用全部失效;而 pop_back、clear 只让末尾/全部迭代器失效,不涉及重分配则其余仍有效。
立即学习“C++免费学习笔记(深入)”;
常见踩坑:
- 在 for 循环中边遍历边
push_back,导致迭代器突然失效(UB) - 用
&v[0]获取首地址后,后续任意可能扩容的操作都让该指针悬空 -
erase返回下一个有效迭代器,但很多人写成v.erase(it); ++it;,造成跳过元素或访问已销毁位置
std::vector v = {1, 2, 3, 4, 5}; for (auto it = v.begin(); it != v.end(); ) { if (*it % 2 == 0) { it = v.erase(it); // 正确:用 erase 返回值更新 it } else { ++it; } }
与 raw Array、其他容器的边界选择
vector 不是万能替代品。小固定尺寸(≤ 4 个元素)、栈上生命周期明确的场景,优先用 std::array 或原生数组——零开销、无堆分配、constexpr 友好;需要频繁中间插入/删除且不关心随机访问,std::list 或 std::forward_list 更合适;只做尾部 push/pop 且要极致性能,std::deque 的双端操作常比 vector 扩容更稳(虽然内存不连续)。
一个容易被忽略的点:std::vector 是特化版本,不满足 Container 要求——它把 bool 压缩存储,operator[] 返回的是代理对象而非 bool&,因此不能取地址、不能绑定到 bool& 引用。真要存布尔值又需引用语义,改用 std::vector。