优先选 std::vector,因其内存连续、随机访问快(O(1)指针运算)、缓存友好;仅当高频在中间插入/删除且迭代器位置已知时才考虑 std::list。

选 std::vector 还是 std::list,不看接口相似性,只看三个硬指标:内存是否连续、随机访问是否需要、插入删除是否集中在中间——满足前两者就选 vector,满足最后一条且高频发生才考虑 list。
为什么 vector 的 [] 访问快,而 list 不支持
因为 vector 是连续内存块,v[i] 等价于 *(v.data() + i),纯指针运算,CPU 缓存预取能一次加载多个相邻元素;list 每个节点分散在堆上,std::next(it, n) 必须逐个跳指针,每次跳都可能触发缺页中断或缓存未命中。实测访问 10 万个 int 时,vector 随机访问比 list 快约 148 倍。
常见错误现象:
- 误用
lst[5]编译失败(list没有重载operator[]) - 用
std::advance(it, n)替代下标,却没意识到这是O(n)操作 - 在循环中反复调用
std::next(lst.begin(), i),把本该O(1)的逻辑写成O(n²)
insert/erase 在中间位置时,vector 和 list 的行为差异
vector::insert(it, x) 或 vector::erase(it) 一旦发生在非尾部,就要移动后续所有元素,时间复杂度 O(n);list::insert(it, x) 或 list::erase(it) 只改前后节点的指针,只要迭代器已知,就是稳定 O(1)。
立即学习“C++免费学习笔记(深入)”;
但注意前提:「已知迭代器位置」。如果你每次都要先 std::find 找位置,那查找本身已是 O(n),整体优势归零。
使用场景建议:
- 频繁在头部插入?用
list::push_front(),别用vector::insert(vec.begin(), x) - 按索引删除第 k 个元素?
vector直接erase(v.begin() + k)更快;list得先std::next(begin(), k),再erase,反而更慢 - 边遍历边删满足条件的元素?
list可安全erase(it++),vector必须用 erase–remove 惯用法,否则迭代器失效
内存占用和缓存表现的实际影响
存 100 万个 int:
-
vector占约 4MB(仅数据,无额外开销) -
list占约 12MB(每个节点含两个指针,64 位系统占 16 字节,加上堆管理开销,实际存储密度常低于 1/3)
这不只是“浪费内存”的问题:链表节点跨页分布会显著增加 TLB miss 和缺页率,在嵌入式或低延迟场景下,list 可能直接拖垮吞吐。而 vector 的连续布局让 CPU 预取器高效工作,遍历速度通常是 list 的 30–50 倍。
容易被忽略的一点:vector 的 reserve() 能彻底规避扩容抖动,但 list 没有类似机制——每次 push_back 都是一次独立堆分配,高并发下易引发锁争用(尤其在旧版 libc++ 中)。


















