C++基础教育第六课:STL标准模板库精要
以下是C++基础教育第六课,聚焦STL标准模板库核心组件,掌握现代C++高效编程的瑞士军刀:
C++基础教育第六课:STL标准模板库精要
一、课程导语
"STL是C++给程序员的礼物——本节课我们将深入探索容器、算法与迭代器的黄金组合,体验工业级代码的优雅与效率。"
二、核心知识点
-
容器家族:顺序容器与关联容器
-
迭代器模式:统一访问接口
-
算法库:泛型编程实践
-
适配器模式:栈与队列实现
-
分配器:内存管理定制
三、实操环节
1. 顺序容器实战
(1) vector动态数组
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> nums; // 空vector
// 尾部插入
nums.push_back(10);
nums.push_back(20);
nums.push_back(30);
// 随机访问
cout << "第2个元素: " << nums[1] << endl; // 20 (无边界检查)
cout << "安全访问: " << nums.at(1) << endl; // 20 (越界抛出异常)
// 迭代器遍历
for(auto it = nums.begin(); it != nums.end(); ++it) {
cout << *it << " "; // 10 20 30
}
// 容量管理
nums.reserve(100); // 预分配空间
cout << "容量: " << nums.capacity() << endl;
return 0;
}
性能特点:
-
随机访问O(1)
-
尾部插入平均O(1)
-
中间插入O(n)
(2) list双向链表
#include <list>
// ...(省略头文件)
list<int> dataList = {1, 2, 3};
// 任意位置插入
auto it = dataList.begin();
++it; // 指向2
dataList.insert(it, 99); // 列表变为1,99,2,3
// 高效删除
dataList.erase(it); // 删除99
// 反向遍历
for(auto rit = dataList.rbegin(); rit != dataList.rend(); ++rit) {
cout << *rit << " "; // 3 2 1
}
适用场景:
-
频繁在任意位置插入/删除
-
不需要随机访问
2. 关联容器进阶
(1) map键值对词典
#include <map>
#include <string>
map<string, int> wordCount;
// 插入元素
wordCount["apple"] = 3;
wordCount.insert({"banana", 5});
// 查找元素
if(wordCount.find("orange") == wordCount.end()) {
cout << "未找到orange" << endl;
}
// 遍历map
for(const auto &pair : wordCount) {
cout << pair.first << ": " << pair.second << endl;
}
底层实现:
-
红黑树保证有序性(按键升序排列)
-
查找/插入/删除时间复杂度O(log n)
(2) unordered_set哈希集合
#include <unordered_set>
unordered_set<int> uniqueNumbers = {1, 2, 3, 2, 1};
// 自动去重,实际存储{1,2,3}
// 快速存在性检查
if(uniqueNumbers.count(2)) {
cout << "2存在集合中" << endl;
}
// 自定义哈希函数示例(用于自定义类型)
struct Point {
int x, y;
};
struct PointHash {
size_t operator()(const Point &p) const {
return hash<int>()(p.x) ^ hash<int>()(p.y);
}
};
unordered_set<Point, PointHash> pointSet;
3. 算法与迭代器
(1) 常用算法示例
#include <algorithm>
#include <numeric> // 数值算法
vector<int> data = {3, 1, 4, 1, 5, 9};
// 排序
sort(data.begin(), data.end()); // 1,1,3,4,5,9
// 查找
auto it = find(data.begin(), data.end(), 4);
if(it != data.end()) {
cout << "找到4,位置: " << distance(data.begin(), it) << endl;
}
// 统计
int count = count_if(data.begin(), data.end(),
[](int x){ return x > 3; }); // 统计大于3的元素
// 累加
int sum = accumulate(data.begin(), data.end(), 0);
(2) 自定义比较函数
// 降序排序
sort(data.begin(), data.end(), greater<int>());
// 自定义结构体排序
struct Student {
string name;
int score;
};
vector<Student> students = {{"Alice",90}, {"Bob",85}, {"Carol",95}};
sort(students.begin(), students.end(),
[](const Student &a, const Student &b) {
return a.score > b.score; // 按分数降序
});
4. 适配器容器
(1) stack后进先出
#include <stack>
stack<int> calcStack;
calcStack.push(10);
calcStack.push(20);
calcStack.push(30);
cout << "栈顶: " << calcStack.top() << endl; // 30
calcStack.pop(); // 移除30
cout << "新栈顶: " << calcStack.top() << endl; // 20
(2) queue先进先出
#include <queue>
queue<string> taskQueue;
taskQueue.push("任务A");
taskQueue.push("任务B");
cout << "下一个任务: " << taskQueue.front() << endl; // 任务A
taskQueue.pop(); // 移除任务A
cout << "新任务: " << taskQueue.front() << endl; // 任务B
四、底层原理剖析
1. 迭代器失效规则
| 操作类型 | vector/string | list/deque | map/set |
|---|---|---|---|
| 插入元素 | 可能失效 | 不失效 | 不失效 |
| 删除元素 | 后续迭代器失效 | 仅被删元素失效 | 仅被删元素失效 |
| 扩容(reserve) | 全部失效 | 不适用 | 不适用 |
安全编程建议:
-
使用
erase返回值更新迭代器:for(auto it = vec.begin(); it != vec.end(); ) { if(*it % 2 == 0) { it = vec.erase(it); // erase返回下一个有效迭代器 } else { ++it; } }
2. 分配器机制
#include <memory>
// 自定义分配器示例
template<typename T>
class MyAllocator {
public:
T* allocate(size_t n) {
cout << "分配 "<< n << " 个T对象" << endl;
return static_cast<T*>(::operator new(n * sizeof(T)));
}
void deallocate(T* p, size_t n) {
cout << "释放 "<< n << " 个T对象" << endl;
::operator delete(p);
}
};
vector<int, MyAllocator<int>> customVec; // 使用自定义分配器
五、课后实战任务
基础挑战
-
实现学生成绩管理系统:
-
使用
map<string, vector<int>>存储学生姓名与成绩列表 -
提供添加成绩、计算平均分功能
-
进阶挑战
-
设计文本词频统计工具:
-
使用
unordered_map<string, int>统计单词出现次数 -
按词频降序输出Top 10高频词
-
-
实现迷宫求解算法:
-
用
queue<pair<int,int>>实现广度优先搜索(BFS) -
记录路径并可视化输出
-
六、常见问题解答
-
Q:vector和list如何选择?
A:
-
需要随机访问 → vector
-
频繁在中间插入/删除 → list
-
元素数量变化大 → vector(预留空间)或deque
-
-
Q:map和unordered_map性能对比?
A:
-
查找/插入平均时间复杂度:
-
map: O(log n)
-
unordered_map: O(1)(最坏情况O(n))
-
-
内存占用:unordered_map通常更高
-
-
Q:STL容器线程安全吗?
A:
-
不同容器实例可安全并发访问
-
同一容器多线程操作需外部同步(如mutex)
-
C++17引入并行算法(
std::execution::par)
-
"STL不是束缚你的枷锁,而是让你站在巨人肩膀上的阶梯——掌握它,你将获得工业级开发的生产力!"
(本课代码已在C++17标准下验证,推荐使用Clang-Tidy检查STL使用规范)
更多推荐

所有评论(0)