C++ STL(Standard Template Library,标准模板库)是C++标准库的核心部分,它提供了一系列通用的、高效的模板类和函数,涵盖了容器、算法、迭代器、函数对象、适配器等核心组件,能极大提升编程效率。下面我会从新手视角,用通俗易懂的方式讲解STL的核心用法。
一、STL核心组成(新手先掌握这3个)
- 容器(Containers):用于存储数据的模板类(如数组、链表、集合),分为:
- 序列式容器:
vector、list、deque(按顺序存储)
- 关联式容器:
map、set(按键/值有序存储)
- 无序容器:
unordered_map、unordered_set(哈希存储,查询更快)
- 迭代器(Iterators):遍历容器的”工具”,类似指针,统一了不同容器的遍历方式。
- 算法(Algorithms):通用的操作函数(如排序、查找、遍历),通过迭代器操作容器数据。
二、最常用STL组件的具体用法
1. 序列式容器:vector(最常用,动态数组)
vector是动态扩容的数组,随机访问速度快,适合频繁读取、尾部增删的场景。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() { vector<int> vec; vector<int> vec2(5, 10);
vec.push_back(1); vec.push_back(3); vec.push_back(2);
cout << "第一个元素:" << vec[0] << endl; cout << "第二个元素:" << vec.at(1) << endl; cout << "尾部元素:" << vec.back() << endl;
cout << "下标遍历:"; for (int i = 0; i < vec.size(); i++) { cout << vec[i] << " "; } cout << endl;
cout << "迭代器遍历:"; for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++) { cout << *it << " "; } cout << endl;
cout << "范围for遍历:"; for (int num : vec) { cout << num << " "; } cout << endl;
cout << "vector大小:" << vec.size() << endl; cout << "vector容量:" << vec.capacity() << endl; vec.sort(vec.begin(), vec.end()); cout << "排序后:"; for (int num : vec) cout << num << " "; cout << endl;
vec.pop_back(); vec.clear(); cout << "清空后大小:" << vec.size() << endl;
return 0; }
|
2. 关联式容器:map(键值对存储)
map以<key, value>键值对存储数据,key唯一且自动排序(升序),适合通过key快速查找value。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| #include <iostream> #include <map> #include <string>
using namespace std;
int main() { map<string, int> scoreMap;
scoreMap["张三"] = 90; scoreMap.insert(pair<string, int>("李四", 85)); scoreMap.insert({"王五", 95});
cout << "张三的分数:" << scoreMap["张三"] << endl; map<string, int>::iterator it = scoreMap.find("赵六"); if (it != scoreMap.end()) { cout << "赵六的分数:" << it->second << endl; } else { cout << "赵六不存在" << endl; }
cout << "所有成绩:" << endl; for (auto iter = scoreMap.begin(); iter != scoreMap.end(); iter++) { cout << iter->first << ":" << iter->second << endl; }
cout << "map大小:" << scoreMap.size() << endl; scoreMap.erase("李四"); scoreMap.clear();
return 0; }
|
3. 算法(Algorithms):通用操作函数
STL算法是独立的函数,通过迭代器操作容器,无需关心容器具体类型,下面是最常用的算法示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include <iostream> #include <vector> #include <algorithm> #include <numeric>
using namespace std;
int main() { vector<int> vec = {5, 2, 8, 1, 9};
sort(vec.begin(), vec.end()); cout << "升序排序:"; for (int num : vec) cout << num << " "; cout << endl;
sort(vec.begin(), vec.end(), greater<int>()); cout << "降序排序:"; for (int num : vec) cout << num << " "; cout << endl;
auto it = find(vec.begin(), vec.end(), 5); if (it != vec.end()) { cout << "找到5,位置:" << it - vec.begin() << endl; }
int cnt = count(vec.begin(), vec.end(), 8); cout << "8的个数:" << cnt << endl;
int sum = accumulate(vec.begin(), vec.end(), 0); cout << "总和:" << sum << endl;
reverse(vec.begin(), vec.end()); cout << "反转后:"; for (int num : vec) cout << num << " "; cout << endl;
return 0; }
|
三、新手使用STL的注意事项
- 头文件必须包含:使用哪个容器/算法,就要包含对应的头文件(如
vector对应<vector>,sort对应<algorithm>)。
- 迭代器的边界:
end()指向的是”最后一个元素的下一位”,遍历结束条件是it != end(),而非it < end()。
- 避免越界访问:
vector的[]操作无越界检查,新手优先用at()(会抛异常,便于调试)。
- 选择合适的容器:
- 频繁随机访问、尾部增删 →
vector;
- 频繁中间增删 →
list;
- 按key查找 →
map/unordered_map(后者查询更快)。
总结
- STL核心是容器(存数据)+ 迭代器(遍历)+ 算法(操作数据),三者通过迭代器解耦,用法统一;
- 新手优先掌握
vector(动态数组)、map(键值对)和常用算法(sort/find/reverse),覆盖80%的日常场景;
- 使用STL时需注意头文件包含、迭代器边界和容器的选择,避免越界和性能问题。
我会为你详细梳理C++ STL中所有常用容器的核心操作,并提供一份完整、可直接运行的示例代码,覆盖每个容器的创建、增删改查、遍历等核心场景。
STL常用容器及核心操作总览
先明确本次覆盖的容器范围(新手必掌握):
| 容器类型 |
名称 |
特点 |
核心适用场景 |
| 序列式容器 |
vector |
动态数组,随机访问快 |
频繁读取、尾部增删 |
| 序列式容器 |
list |
双向链表,中间增删快 |
频繁插入/删除(非尾部) |
| 序列式容器 |
deque |
双端队列,两端增删快 |
队列/栈场景 |
| 关联式容器 |
set |
有序不重复集合 |
去重、有序查找 |
| 关联式容器 |
map |
有序键值对(key唯一) |
按key查找value |
| 无序容器 |
unordered_set |
哈希集合,查询O(1) |
快速去重、查找 |
| 无序容器 |
unordered_map |
哈希键值对,查询O(1) |
高频按key查询 |
| 容器适配器 |
stack |
栈(后进先出) |
栈操作(push/pop/top) |
| 容器适配器 |
queue |
队列(先进先出) |
队列操作(push/pop/front) |
完整示例代码(覆盖所有容器核心操作)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
| #include <iostream> #include <vector> #include <list> #include <deque> #include <set> #include <map> #include <unordered_set> #include <unordered_map> #include <stack> #include <queue> #include <algorithm> #include <string>
using namespace std;
void printSeparator(const string& containerName) { cout << "\n=====================================" << endl; cout << "【" << containerName << " 操作示例】" << endl; cout << "=====================================\n" << endl; }
int main() { printSeparator("vector"); vector<int> vec; vec.push_back(10); vec.push_back(20); vec.push_back(30); vec.insert(vec.begin() + 1, 15); cout << "vector第1个元素:" << vec[0] << endl; cout << "vector第2个元素:" << vec.at(1) << endl; cout << "vector尾部元素:" << vec.back() << endl; cout << "vector大小:" << vec.size() << endl; cout << "vector容量:" << vec.capacity() << endl; cout << "vector遍历:"; for (int num : vec) cout << num << " "; cout << endl; vec[2] = 25; cout << "修改后vector遍历:"; for (int num : vec) cout << num << " "; cout << endl; vec.pop_back(); vec.erase(vec.begin() + 1); cout << "删除后vector遍历:"; for (int num : vec) cout << num << " "; cout << endl; vec.clear(); cout << "清空后vector大小:" << vec.size() << endl;
printSeparator("list"); list<string> lst; lst.push_back("apple"); lst.push_front("banana"); lst.insert(next(lst.begin()), "orange"); cout << "list头部元素:" << lst.front() << endl; cout << "list尾部元素:" << lst.back() << endl; cout << "list大小:" << lst.size() << endl; cout << "list遍历:"; for (const string& s : lst) cout << s << " "; cout << endl; auto lstIt = find(lst.begin(), lst.end(), "orange"); if (lstIt != lst.end()) *lstIt = "grape"; cout << "修改后list遍历:"; for (const string& s : lst) cout << s << " "; cout << endl; lst.pop_front(); lst.pop_back(); lst.erase(find(lst.begin(), lst.end(), "grape")); cout << "删除后list遍历:"; for (const string& s : lst) cout << s << " "; cout << endl; lst.clear();
printSeparator("deque"); deque<int> dq; dq.push_back(100); dq.push_front(200); dq.insert(dq.begin() + 1, 150); cout << "deque头部:" << dq.front() << endl; cout << "deque尾部:" << dq.back() << endl; cout << "deque第2个元素:" << dq[1] << endl; cout << "deque遍历:"; for (int num : dq) cout << num << " "; cout << endl; dq.pop_front(); dq.pop_back(); cout << "删除后deque遍历:"; for (int num : dq) cout << num << " "; cout << endl; dq.clear();
printSeparator("set"); set<int> s; s.insert(5); s.insert(2); s.insert(8); s.insert(2); cout << "set大小:" << s.size() << endl; auto setIt = s.find(5); if (setIt != s.end()) cout << "找到元素:" << *setIt << endl; cout << "set遍历(升序):"; for (int num : s) cout << num << " "; cout << endl; s.erase(2); cout << "删除后set遍历:"; for (int num : s) cout << num << " "; cout << endl; s.clear();
printSeparator("map"); map<string, int> mp; mp["张三"] = 90; mp.insert({"李四", 85}); mp.insert(pair<string, int>("王五", 95)); cout << "张三的分数:" << mp["张三"] << endl; auto mapIt = mp.find("李四"); if (mapIt != mp.end()) cout << "李四的分数:" << mapIt->second << endl; cout << "map遍历:" << endl; for (const auto& pair : mp) { cout << pair.first << ":" << pair.second << endl; } mp["张三"] = 92; mp.erase("王五"); cout << "删除后map遍历:" << endl; for (const auto& pair : mp) { cout << pair.first << ":" << pair.second << endl; } mp.clear();
printSeparator("unordered_set"); unordered_set<string> uset; uset.insert("cat"); uset.insert("dog"); uset.insert("bird"); cout << "是否存在dog:" << (uset.find("dog") != uset.end() ? "是" : "否") << endl; cout << "unordered_set遍历:"; for (const string& animal : uset) cout << animal << " "; cout << endl; uset.erase("cat"); uset.clear();
printSeparator("unordered_map"); unordered_map<int, string> umap; umap[101] = "语文"; umap[102] = "数学"; umap[103] = "英语"; cout << "102对应的科目:" << umap[102] << endl; cout << "unordered_map遍历:" << endl; for (const auto& pair : umap) { cout << pair.first << ":" << pair.second << endl; } umap.erase(101); umap.clear();
printSeparator("stack"); stack<int> stk; stk.push(1); stk.push(2); stk.push(3); cout << "栈顶元素:" << stk.top() << endl; cout << "栈大小:" << stk.size() << endl; stk.pop(); cout << "出栈后栈顶:" << stk.top() << endl; cout << "栈是否为空:" << (stk.empty() ? "是" : "否") << endl; while (!stk.empty()) stk.pop();
printSeparator("queue"); queue<string> que; que.push("A"); que.push("B"); que.push("C"); cout << "队首元素:" << que.front() << endl; cout << "队尾元素:" << que.back() << endl; que.pop(); cout << "出队后队首:" << que.front() << endl; while (!que.empty()) que.pop();
return 0; }
|
代码运行说明
- 编译环境:支持C++11及以上的编译器(如GCC、Clang、MSVC);
- 编译命令(Linux/macOS):
g++ -std=c++11 stl_container.cpp -o stl_container;
- 运行:
./stl_container;
- 输出:每个容器的操作会按顺序输出,包含增删改查、遍历的结果,便于你对照理解。
各容器核心操作总结
| 容器 |
核心新增操作 |
核心删除操作 |
核心访问方式 |
特殊点 |
| vector |
push_back、insert |
pop_back、erase、clear |
[]、at、front、back |
支持随机访问,动态扩容 |
| list |
push_back、push_front、insert |
pop_back、pop_front、erase |
front、back(无下标) |
双向链表,中间增删快 |
| deque |
push_back、push_front、insert |
pop_back、pop_front、erase |
[]、front、back |
双端队列,两端操作快 |
| set |
insert |
erase、clear |
find(迭代器访问) |
有序、去重,无修改操作 |
| map |
[]赋值、insert |
erase(按key)、clear |
[]、find(->first/second) |
key唯一,有序 |
| unordered_set |
insert |
erase、clear |
find |
无序、哈希,查询O(1) |
| unordered_map |
[]赋值、insert |
erase(按key)、clear |
[]、find |
无序、哈希,查询比map快 |
| stack |
push |
pop |
top |
后进先出,无遍历/下标 |
| queue |
push |
pop |
front、back |
先进先出,无遍历/下标 |
总结
- 序列式容器(vector/list/deque):核心关注”增删的位置”(尾部/头部/中间),vector支持随机访问,list适合中间增删,deque兼顾两端操作;
- 关联式/无序容器(set/map/unordered_*):核心是”按值/键操作”,set/map自动排序,unordered_*基于哈希查询更快;
- 容器适配器(stack/queue):操作受限(栈:仅栈顶;队列:仅队首/队尾),适合特定的先进后出/先进先出场景。
这份代码覆盖了每个容器的高频操作,你可以直接运行并修改参数,直观理解每个操作的效果,是新手入门STL容器的最佳实践模板。