C++ 标准模板库(STL)是 C++ 语言的基石之一,它提供了一套性能卓越、经过严格测试的通用算法和数据结构。其中,容器是 STL 最核心的部分,它们是用于管理和存储对象集合的类模板。正确地选择容器,不仅能让代码更简洁、更安全,还能显著提升程序的性能。
本文将全面介绍 C++ 中常见的各类容器,分析它们的内部实现、优缺点以及最佳适用场景,帮助你今后在项目开发中做出明智的选择。
C++ 容器主要可以分为三类:顺序容器、关联容器和无序关联容器。
顺序容器中的元素按照严格的线性顺序排列。你可以精确地控制每个元素的位置。
std::vector[] 或 .at() 进行随机访问的时间复杂度为 O(1),并且由于内存连续,能很好地利用 CPU 缓存。.push_back(), .pop_back())的平均时间复杂度为 O(1)。vector 容量不足时,它会重新分配一块更大的内存,并将所有旧元素拷贝过去,这可能是一个耗时的操作。std::deque (Double-Ended Queue)vector(需要两次指针解引用),但时间复杂度仍为 O(1)。vector 类似,中间操作的时间复杂度为 O(n)。vector,遍历速度可能稍慢。std::listlist[i])访问元素。要访问第 n 个元素,必须从头或尾开始遍历 n 次,时间复杂度为 O(n)。std::array (C++11)关联容器根据键 (key) 来高效地排序和存储元素。它们非常适合用于快速查找。
std::mapstd::setmap 一样,内部也是由红黑树实现,元素自动排序。
std::multimap和std::multiset分别是map和set的多键版本,它们允许存储重复的键。
这类容器在 C++11 中引入,它们也存储键或键值对,但基于哈希表 (Hash Table) 实现,不保证元素有序,换来的是更快的平均性能。
std::unordered_mapstd::map 的常用高性能替代品。std::unordered_set为了方便选择,下表总结了各类容器的特点:
| 需求 | 推荐容器 | 备选方案 | 时间复杂度 (平均) |
|---|---|---|---|
| 快速随机访问 | std::vector | std::deque, std::array | O(1) |
| 大量中间插入/删除 | std::list | std::forward_list | O(1) |
| 快速两端插入/删除 | std::deque | std::list | O(1) |
| 键值对存储 (有序) | std::map | std::multimap | O(log n) |
| 键值对存储 (最快查找) | std::unordered_map | std::unordered_multimap | O(1) |
| 存储唯一元素 (有序) | std::set | std::multiset | O(log n) |
| 存储唯一元素 (最快查找) | std::unordered_set | std::unordered_multiset | O(1) |
通用建议:
std::vector 通常是最好的第一选择。它的性能优秀且用途广泛。std::unordered_map 是 std::map 的高性能替代品。std::list。