当前位置: 首页 > news >正文

C++STL标准模板库详解

一、引言

STL(Standard Template Library)是 C++ 标准库的核心组成部分,其中容器(Containers) 作为数据存储的基础组件,为开发者提供了丰富的数据结构选择。本文将聚焦 STL 容器的核心类型,结合具体 C++ 代码示例详解其特性、用法及适用场景,帮助读者在实际开发中精准选型。

二、序列容器(Sequence Containers)

序列容器按元素插入顺序存储数据,支持按位置访问,是最常用的容器类型。

2.1 std::vector:动态数组

特性:内存连续存储,支持随机访问,尾部插入 / 删除高效,中间插入 / 删除开销大。
适用场景:需要频繁随机访问、尾部操作的场景(如存储动态列表、缓存数据)。

代码示例:
#include <iostream>
#include <vector>
using namespace std;int main() {// 1. 初始化方式vector<int> vec1; // 空vectorvector<int> vec2(5, 10); // 5个元素,每个初始化为10vector<int> vec3 = {1, 2, 3, 4, 5}; // 初始化列表// 2. 尾部插入元素vec1.push_back(6);vec1.push_back(7);// 3. 随机访问([]或at())cout << "vec3[2] = " << vec3[2] << endl; // 输出3cout << "vec3.at(3) = " << vec3.at(3) << endl; // 输出4(带越界检查)// 4. 遍历元素(迭代器)cout << "vec3元素:";for (vector<int>::iterator it = vec3.begin(); it != vec3.end(); ++it) {cout << *it << " ";}cout << endl;// 5. 容量与大小cout << "vec3大小:" << vec3.size() << endl; // 5cout << "vec3容量:" << vec3.capacity() << endl; // 至少5(动态扩容)// 6. 中间插入元素(效率较低)vec3.insert(vec3.begin() + 2, 99); // 在索引2处插入99cout << "插入后vec3[2] = " << vec3[2] << endl; // 输出99return 0;
}

2.2 std::list:双向链表

特性:非连续存储,通过指针连接元素,任意位置插入 / 删除高效,不支持随机访问。
适用场景:需要频繁在中间插入 / 删除元素的场景(如实现链表、队列、邻接表)。

代码示例:
#include <iostream>
#include <list>
using namespace std;int main() {// 初始化列表list<int> lst = {3, 1, 4, 1, 5};// 1. 头部/尾部操作lst.push_front(0); // 头部插入0lst.push_back(6); // 尾部插入6// 2. 遍历(不支持[]访问,需迭代器)cout << "list元素:";for (auto it = lst.begin(); it != lst.end(); ++it) {cout << *it << " ";}cout << endl; // 输出:0 3 1 4 1 5 6// 3. 中间插入/删除auto it = lst.begin();advance(it, 2); // 移动迭代器到第2个元素(值为3的下一个元素1)lst.insert(it, 99); // 在1前插入99cout << "插入后元素:";for (int num : lst) { // 范围for循环cout << num << " ";}cout << endl; // 输出:0 3 99 1 4 1 5 6// 4. 删除指定值的元素lst.remove(1); // 删除所有值为1的元素cout << "删除1后元素:";for (int num : lst) {cout << num << " ";}cout << endl; // 输出:0 3 99 4 5 6return 0;
}

2.3 std::deque:双端队列

特性:分段连续内存,支持两端高效插入 / 删除,随机访问效率略低于 vector。
适用场景:需要频繁在头部和尾部操作的场景(如实现队列、缓冲区)。

代码示例:
#include <iostream>
#include <deque>
using namespace std;int main() {deque<int> dq;// 1. 两端插入dq.push_back(10); // 尾部插入dq.push_front(5); // 头部插入dq.push_back(20);dq.push_front(1);// 2. 随机访问cout << "dq[1] = " << dq[1] << endl; // 输出5cout << "dq.at(2) = " << dq.at(2) << endl; // 输出10// 3. 遍历cout << "deque元素:";for (int num : dq) {cout << num << " ";}cout << endl; // 输出:1 5 10 20// 4. 两端删除dq.pop_front(); // 删除头部元素1dq.pop_back(); // 删除尾部元素20cout << "删除后元素:";for (int num : dq) {cout << num << " ";}cout << endl; // 输出:5 10return 0;
}

三、关联容器(Associative Containers)

关联容器基于键(Key)存储元素,内部通常用红黑树实现,元素自动排序,支持高效查找。

3.1 std::set:有序唯一集合

特性:元素唯一且按升序排列,插入 / 查找 / 删除时间复杂度 O (log n)。
适用场景:需要去重并保持有序的集合(如存储唯一 ID、实现集合运算)。

代码示例:
#include <iostream>
#include <set>
using namespace std;int main() {// 初始化(自动排序+去重)set<int> s = {5, 2, 8, 2, 5, 9};// 1. 插入元素s.insert(3);// 2. 遍历(默认升序)cout << "set元素:";for (int num : s) {cout << num << " ";}cout << endl; // 输出:2 3 5 8 9// 3. 查找元素auto it = s.find(5);if (it != s.end()) {cout << "找到元素:" << *it << endl;} else {cout << "未找到元素" << endl;}// 4. 删除元素s.erase(8); // 删除值为8的元素cout << "删除8后元素:";for (int num : s) {cout << num << " ";}cout << endl; // 输出:2 3 5 9return 0;
}

3.2 std::map:有序键值对映射

特性:键唯一且按升序排列,通过键快速访问值,时间复杂度 O (log n)。
适用场景:需要键值对映射的场景(如字典、配置表、索引表)。

代码示例:
#include <iostream>
#include <map>
#include <string>
using namespace std;int main() {// 初始化键值对(键为int,值为string)map<int, string> student;// 1. 插入元素(三种方式)student[101] = "Alice"; // 下标法student.insert(pair<int, string>(102, "Bob")); // pair插入student.emplace(103, "Charlie"); // emplace(更高效)// 2. 遍历键值对cout << "学生信息:" << endl;for (auto& pair : student) { // 注意用引用避免拷贝cout << "学号:" << pair.first << ",姓名:" << pair.second << endl;}// 输出:// 学号:101,姓名:Alice// 学号:102,姓名:Bob// 学号:103,姓名:Charlie// 3. 查找键对应的值int id = 102;auto it = student.find(id);if (it != student.end()) {cout << id << "对应的姓名:" << it->second << endl; // 输出Bob}// 4. 删除键student.erase(101);cout << "删除101后学号101是否存在:" << (student.count(101) ? "是" : "否") << endl; // 输出否return 0;
}

3.3 std::multiset 与 std::multimap:允许重复键

特性multiset 允许重复元素,multimap 允许重复键,均有序排列。
适用场景:需要存储重复元素 / 键的场景(如统计频率、一对多映射)。

代码示例(multimap):
#include <iostream>
#include <map>
#include <string>
using namespace std;int main() {// 课程-学生映射(一门课对应多个学生)multimap<string, string> course;// 插入重复键course.insert({"Math", "Alice"});course.insert({"Math", "Bob"});course.insert({"Physics", "Charlie"});course.insert({"Math", "David"});// 1. 遍历所有键值对cout << "所有课程学生:" << endl;for (auto& pair : course) {cout << pair.first << ":" << pair.second << endl;}// 2. 查找特定键的所有值string key = "Math";cout << "\n" << key << "的学生:" << endl;auto range = course.equal_range(key); // 获取键为Math的范围for (auto it = range.first; it != range.second; ++it) {cout << it->second << endl; // 输出Alice、Bob、David}return 0;
}

四、无序关联容器(Unordered Associative Containers)

C++11 引入,基于哈希表实现,元素无序,平均插入 / 查找 / 删除时间复杂度 O (1)。

4.1 std::unordered_set:无序唯一集合

特性:元素唯一、无序,哈希表存储,查找效率极高(无排序开销)。
适用场景:只需去重和快速查找,不关心顺序的场景(如黑名单、存在性判断)。

代码示例:
#include <iostream>
#include <unordered_set>
using namespace std;int main() {unordered_set<string> fruits = {"apple", "banana", "orange"};// 1. 插入元素fruits.insert("grape");// 2. 遍历(无序)cout << "无序集合元素:";for (auto& fruit : fruits) {cout << fruit << " ";}cout << endl; // 输出顺序不确定// 3. 快速查找string target = "banana";if (fruits.count(target)) { // count()判断存在性cout << target << " 存在于集合中" << endl;}return 0;
}

4.2 std::unordered_map:无序键值对映射

特性:键唯一、无序,哈希表存储,适合高频查找场景。
适用场景:需要快速键值映射且不关心顺序的场景(如缓存、哈希表)。

代码示例:
#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;int main() {// 姓名-年龄映射(无序)unordered_map<string, int> age;age["Alice"] = 20;age["Bob"] = 22;age["Charlie"] = 21;// 1. 遍历(无序)cout << "姓名-年龄:" << endl;for (auto& pair : age) {cout << pair.first << ":" << pair.second << endl;}// 2. 查找效率对比(哈希表 vs 红黑树)// 对于高频查找,unordered_map性能优于mapcout << "Bob的年龄:" << age["Bob"] << endl;return 0;
}

五、容器适配器(Container Adapters)

基于基础容器封装的特殊接口,简化特定场景使用。

5.1 std::stack:栈(LIFO)

特性:后进先出,基于 deque 默认实现,支持push(入栈)、pop(出栈)、top(取栈顶)。
适用场景:表达式求值、括号匹配、深度优先搜索(DFS)。

代码示例:
#include <iostream>
#include <stack>
using namespace std;int main() {stack<int> st;// 入栈st.push(1);st.push(2);st.push(3);// 栈顶元素cout << "栈顶元素:" << st.top() << endl; // 输出3// 出栈st.pop(); // 删除栈顶元素3cout << "出栈后栈顶:" << st.top() << endl; // 输出2// 栈大小cout << "栈大小:" << st.size() << endl; // 输出2return 0;
}

5.2 std::queue:队列(FIFO)

特性:先进先出,基于 deque 默认实现,支持push(入队)、pop(出队)、front(队首)。
适用场景:任务调度、广度优先搜索(BFS)、消息队列。

代码示例:
#include <iostream>
#include <queue>
using namespace std;int main() {queue<string> q;// 入队q.push("任务1");q.push("任务2");q.push("任务3");// 队首元素cout << "队首任务:" << q.front() << endl; // 输出任务1// 出队q.pop(); // 移除任务1cout << "出队后队首:" << q.front() << endl; // 输出任务2// 队列大小cout << "队列大小:" << q.size() << endl; // 输出2return 0;
}

5.3 std::priority_queue:优先队列

特性:元素按优先级排序(默认最大元素优先),基于 vector 默认实现。
适用场景:定时器、任务调度(高优先级先执行)、最大 / 最小堆场景。

代码示例:
#include <iostream>
#include <queue>
using namespace std;int main() {// 最大优先队列(默认)priority_queue<int> maxHeap;maxHeap.push(3);maxHeap.push(1);maxHeap.push(5);cout << "最大堆顶:" << maxHeap.top() << endl; // 输出5// 最小优先队列(通过greater<>实现)priority_queue<int, vector<int>, greater<int>> minHeap;minHeap.push(3);minHeap.push(1);minHeap.push(5);cout << "最小堆顶:" << minHeap.top() << endl; // 输出1return 0;
}

六、容器选型决策指南

容器类型核心特性时间复杂度(插入 / 查找 / 删除)适用场景
vector连续内存,随机访问尾部 O (1),中间 O (n) / O (1)随机访问、尾部操作多
list双向链表,任意位置操作高效O(1) / O(n)频繁中间插入 / 删除
deque双端操作高效,随机访问两端 O (1) / O (1)双端频繁操作
set/map有序,唯一键,红黑树O(log n) / O(log n)有序集合、键值映射,需排序
unordered_set/unordered_map无序,哈希表平均 O (1) / 平均 O (1)高频查找,不关心顺序
stack/queue适配器,LIFO/FIFOO(1)栈 / 队列特定场景
priority_queue优先级排序O(log n)高优先级任务调度

七、总结

STL 容器为 C++ 开发者提供了开箱即用的数据结构解决方案,掌握各类容器的特性和适用场景是编写高效代码的基础。实际开发中需根据访问方式、操作频率、排序需求等因素选型:

  • 需随机访问选vector/deque
  • 需有序且高效查找选set/map
  • 需极致查找性能且无序选unordered_*
  • 需特定数据结构行为选适配器(stack/queue等)。
http://www.dtcms.com/a/334905.html

相关文章:

  • 【渗透实战】无下载器环境(curl/wget)下玩转 Metasploit 自动利用
  • ES操作手册
  • 一、内核初始化中与内存管理相关的函数
  • C语言:文件操作详解
  • 微软Wasm学习-创建一个最简单的c#WebAssembly测试工程
  • 【项目实战】利用AI生成式编程生成控制镜头变倍,变焦,光圈的Shell脚本(一)
  • 如何在FastAPI中玩转APScheduler,实现动态定时任务的魔法?
  • Redis7学习--详解 主从复制
  • 利用cursor+MCP实现浏览器自动化释放双手
  • 自动驾驶中的传感器技术24.1——Camera(16)
  • 企业级Java项目金融应用领域——银行系统(补充)
  • python线程学习
  • 一文了解金融合规
  • 什么是模型预测控制?
  • 算法训练营day52 图论③ 101.孤岛的总面积、102.沉没孤岛、103.水流问题、104.建造最大岛屿
  • PTPX分析中,如何处理fsdb文件过大的问题?
  • 【C#补全计划】Lambda表达式
  • ESP32-S3_ES8311音频输出使用
  • java内存模型:
  • Ubuntu 25.04更新了哪些内容揭秘
  • PHP反序列化的CTF题目环境和做题复现第1集
  • lesson40:PyMySQL完全指南:从基础到高级的Python MySQL交互
  • 【大语言模型 00】导读
  • 【Docker】Ubuntu上安装Docker(网络版)
  • 双指针和codetop复习
  • Hexo 双分支部署指南:从原理到 Netlify 实战
  • 【遥感图像技术系列】遥感图像风格迁移的研究进展一览
  • SymPy 矩阵到 NumPy 数组的全面转换指南
  • Redis 04 Reactor
  • eChart饼环pie中间显示总数_2个以上0值不挤掉