vector 用法与容量
更新时间:2026-08-27。本文是
languages/cpp/主题入门层第 32 篇,STL 子族开篇(存量stl-containers拆解迁入)。vector是 C++ 的默认容器:动态数组、连续内存、自动扩容。它最大的坑藏在"容量 vs 大小"这对概念里——push_back为什么会突然慢一下?reserve凭什么救场?本篇讲透。
本文要回答的问题
vector的基本操作有哪些?和 C 数组什么关系?- 容量(capacity)和大小(size)有什么区别?
push_back扩容为什么是性能陷阱?reserve怎么救?
一、vector 的基本用法
std::vector 是"能自动长大的数组":
#include <vector>
std::vector<int> v; // 空数组
v.push_back(1); // 末尾追加
v.push_back(2);
v.push_back(3);
v.size(); // 元素个数 = 3
v[0]; // 随机访问 O(1),和数组一样快
v.at(0); // 带边界检查的访问(越界抛异常)
v.empty(); // 是否为空
// 遍历
for (int x : v) { /* ... */ } // 范围 for
for (auto& x : v) { x *= 2; } // 修改元素加引用
// 初始化
std::vector<int> w = {1, 2, 3}; // 列表初始化
std::vector<int> z(10, 5); // 10 个 5v[0] 和数组下标一样 O(1) 随机访问、不检查边界(越界是未定义行为);想要安全版用 .at(0),越界会抛 std::out_of_range 异常。性能敏感处用 [],图省心用 at。
内存连续是 vector 的灵魂:元素在内存里一个挨一个,遍历时按地址顺序读,缓存命中率极高(第 09 篇循环那套缓存理论在这里直接受益)。这也是 vector 成为默认首选的根本原因。
二、大小 vs 容量
两个概念必须分清:
std::vector<int> v;
v.reserve(100); // 预分配能装 100 个元素的内存
v.size(); // 大小:当前实际有多少个元素 = 0
v.capacity(); // 容量:当前分配的内存能装多少个 = 100- size(大小):现在有几个元素;
- capacity(容量):已经申请了多少空间,还能塞几个不重新分配。
push_back 一个新元素,size 加 1;只有当 size 要超过 capacity 时,才触发扩容。
三、扩容:push_back 为什么偶尔卡一下
vector 的空间是连续内存,满了怎么办?重新找一块更大的内存、把旧元素全搬过去:

扩容本身是 O(n):申请新内存 + 搬全部元素。虽然容量按倍数增长(通常 1.5~2 倍),均摊下来 push_back 还是 O(1),但扩容发生的那一次会明显卡一下——高频插入场景下,这种间歇卡顿不可接受。
reserve 救场:提前知道要装多少,就 v.reserve(n) 把容量一次到位:
std::vector<int> v;
v.reserve(1000000); // 先申请好
for (int i = 0; i < 1000000; ++i) {
v.push_back(i); // 全程不扩容,稳定 O(1)
}对比 resize:resize(n) 是改变大小(多出的元素用默认值填),reserve(n) 只改容量不动大小。先 reserve 再 push_back 是高频插入的标准姿势。
四、和 C 数组对比
| 对比项 | C 数组 | C++ std::vector |
|---|---|---|
| 大小 | 编译期固定 | 动态增长 |
| 越界检查 | 无 | .at() 可选 |
| 长度 | 要自己记(sizeof(arr)/sizeof(arr[0])) | .size() |
| 传参 | 退化指针 + 长度 | 直接传引用 |
| 扩容 | 手动 realloc | 自动 |
| 栈/堆 | 取决于声明位置 | 元素在堆上 |
C 数组的痛点全在这张表里:长度要自己记、传参要带长度、越界没商量。vector 把这些全包了。C 里"数组 + 长度"当参数传来传去,C++ 一个 const std::vector<int>& 搞定。
五、与本站主线衔接
- 为什么 vector 遍历比 list 快——缓存局部性,见 L3 缓存与局部性;
vector扩容的堆分配会成为性能热点,见perf剖析 与内存分配;- 迭代器与范围 for 的底层,见 迭代器与范围 for;
- 下一篇:
std::string深入——string 也是容器。
一句话总结
vector 是动态数组:连续内存、O(1) 随机访问、自动扩容,是 C++ 默认首选容器;size 是"有几个元素"、capacity 是"能装几个",扩容会新开内存+搬运全部元素(一次 O(n) 卡顿),高频插入前 reserve 预分配;对比 C 数组,vector 自带 .size()、.at() 边界检查,不用手记长度。