概述
C++ 标准模板库(Standard Template Library,STL)是C++标准库的核心组成部分,提供了一组通用的模板类和函数,实现了常见的数据结构和算法。STL基于泛型编程思想,具有高度可复用性和效率。
核心组件
1. 容器(Containers)
容器用于存储和管理数据集合。
顺序容器
#include <iostream>
#include <vector>
#include <deque>
#include <list>
#include <array>
// vector - 动态数组
void vector_example() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 添加元素
vec.push_back(6);
vec.insert(vec.begin(), 0);
// 访问元素
std::cout << "第一个元素: " << vec.front() << std::endl;
std::cout << "最后一个元素: " << vec.back() << std::endl;
std::cout << "第三个元素: " << vec[2] << std::endl; // 不检查边界
std::cout << "第三个元素: " << vec.at(2) << std::endl; // 检查边界
// 遍历
for (int num : vec) {
std::cout << num << " ";
}
std::cout << std::endl;
// 容量信息
std::cout << "大小: " << vec.size() << std::endl;
std::cout << "容量: " << vec.capacity() << std::endl;
}
// deque - 双端队列
void deque_example() {
std::deque<int> dq = {2, 3, 4};
// 两端操作
dq.push_front(1);
dq.push_back(5);
for (int num : dq) {
std::cout << num << " ";
}
std::cout << std::endl;
}
// list - 双向链表
void list_example() {
std::list<int> lst = {1, 2, 3, 4, 5};
// 插入删除
auto it = std::next(lst.begin(), 2); // 指向第三个元素
lst.insert(it, 99);
lst.erase(std::prev(lst.end())); // 删除最后一个元素
// 链表特有操作
lst.sort();
lst.unique();
for (int num : lst) {
std::cout << num << " ";
}
std::cout << std::endl;
}
关联容器
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
// set - 有序集合
void set_example() {
std::set<int> s = {5, 2, 8, 1, 9};
// 插入
s.insert(3);
s.insert(5); // 重复元素,不会插入
// 查找
auto it = s.find(3);
if (it != s.end()) {
std::cout << "找到元素: " << *it << std::endl;
}
// 遍历(有序)
for (int num : s) {
std::cout << num << " ";
}
std::cout << std::endl;
// 多重集合允许重复
std::multiset<int> ms = {1, 2, 2, 3, 3, 3};
std::cout << "数字3的出现次数: " << ms.count(3) << std::endl;
}
// map - 有序映射
void map_example() {
std::map<std::string, int> scores = {
{"Alice", 90},
{"Bob", 85},
{"Charlie", 95}
};
// 插入
scores["David"] = 88;
scores.insert({"Eve", 92});
// 访问
std::cout << "Alice的分数: " << scores["Alice"] << std::endl;
std::cout << "Bob的分数: " << scores.at("Bob") << std::endl;
// 遍历
for (const auto& pair : scores) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
// 查找
auto it = scores.find("Charlie");
if (it != scores.end()) {
std::cout << "找到Charlie,分数: " << it->second << std::endl;
}
}
// 无序容器(哈希表)
void unordered_example() {
std::unordered_map<std::string, int> word_count;
// 统计单词出现次数
std::string text = "apple banana apple orange banana apple";
std::string word;
std::istringstream iss(text);
while (iss >> word) {
word_count[word]++;
}
for (const auto& pair : word_count) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
}
容器适配器
#include <stack>
#include <queue>
void adapter_example() {
// stack - 栈
std::stack<int> stk;
stk.push(1);
stk.push(2);
stk.push(3);
std::cout << "栈顶元素: " << stk.top() << std::endl;
stk.pop();
std::cout << "弹出后栈顶: " << stk.top() << std::endl;
// queue - 队列
std::queue<int> q;
q.push(1);
q.push(2);
q.push(3);
std::cout << "队首: " << q.front() << std::endl;
std::cout << "队尾: " << q.back() << std::endl;
q.pop();
std::cout << "出队后队首: " << q.front() << std::endl;
// priority_queue - 优先队列
std::priority_queue<int> pq;
pq.push(3);
pq.push(1);
pq.push(4);
pq.push(2);
std::cout << "优先队列(最大堆): ";
while (!pq.empty()) {
std::cout << pq.top() << " ";
pq.pop();
}
std::cout << std::endl;
// 最小堆
std::priority_queue<int, std::vector<int>, std::greater<int>> min_pq;
min_pq.push(3);
min_pq.push(1);
min_pq.push(4);
std::cout << "最小堆: " << min_pq.top() << std::endl;
}
2. 迭代器(Iterators)
迭代器用于访问容器中的元素,提供统一的遍历接口。
#include <iterator>
#include <algorithm>
void iterator_example() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 不同类型迭代器
std::cout << "顺序遍历: ";
for (auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
std::cout << "逆序遍历: ";
for (auto it = vec.rbegin(); it != vec.rend(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 迭代器类别
std::vector<int>::iterator random_it = vec.begin(); // 随机访问迭代器
std::list<int>::iterator bidirectional_it; // 双向迭代器
// 迭代器操作
auto it = vec.begin();
std::advance(it, 2); // 前进2个位置
std::cout << "前进2位: " << *it << std::endl;
// 计算距离
auto dist = std::distance(vec.begin(), vec.end());
std::cout << "容器大小: " << dist << std::endl;
}
3. 算法(Algorithms)
STL提供丰富的通用算法,大多数定义在 <algorithm>头文件中。
#include <algorithm>
#include <numeric>
void algorithm_example() {
std::vector<int> vec = {5, 2, 8, 1, 9, 3, 7, 4, 6};
// 排序算法
std::sort(vec.begin(), vec.end());
std::cout << "排序后: ";
for (int num : vec) std::cout << num << " ";
std::cout << std::endl;
// 查找算法
auto it = std::find(vec.begin(), vec.end(), 7);
if (it != vec.end()) {
std::cout << "找到7,位置: " << std::distance(vec.begin(), it) << std::endl;
}
// 二分查找(需先排序)
bool found = std::binary_search(vec.begin(), vec.end(), 5);
std::cout << "二分查找5: " << (found ? "找到" : "未找到") << std::endl;
// 计数
int count_5 = std::count(vec.begin(), vec.end(), 5);
std::cout << "数字5出现次数: " << count_5 << std::endl;
// 累加
int sum = std::accumulate(vec.begin(), vec.end(), 0);
std::cout << "总和: " << sum << std::endl;
// 变换
std::vector<int> squared;
std::transform(vec.begin(), vec.end(), std::back_inserter(squared),
[](int x) { return x * x; });
std::cout << "平方: ";
for (int num : squared) std::cout << num << " ";
std::cout << std::endl;
// 复制
std::vector<int> copy_vec(vec.size());
std::copy(vec.begin(), vec.end(), copy_vec.begin());
// 删除和擦除模式
vec.erase(std::remove_if(vec.begin(), vec.end(),
[](int x) { return x % 2 == 0; }), // 删除偶数
vec.end());
std::cout << "删除偶数后: ";
for (int num : vec) std::cout << num << " ";
std::cout << std::endl;
// 最大值最小值
auto max_it = std::max_element(copy_vec.begin(), copy_vec.end());
auto min_it = std::min_element(copy_vec.begin(), copy_vec.end());
std::cout << "最大值: " << *max_it << ", 最小值: " << *min_it << std::endl;
}
4. 函数对象(Functors)和Lambda表达式
#include <functional>
void functor_example() {
// 内置函数对象
std::plus<int> add;
std::cout << "3 + 5 = " << add(3, 5) << std::endl;
std::greater<int> greater_than;
std::cout << "5 > 3? " << greater_than(5, 3) << std::endl;
// 自定义函数对象
struct Square {
int operator()(int x) const {
return x * x;
}
};
Square square;
std::cout << "4的平方: " << square(4) << std::endl;
// Lambda表达式
std::vector<int> vec = {1, 2, 3, 4, 5};
// 使用Lambda过滤偶数
std::cout << "偶数: ";
std::for_each(vec.begin(), vec.end(), [](int x) {
if (x % 2 == 0) {
std::cout << x << " ";
}
});
std::cout << std::endl;
// 带捕获的Lambda
int threshold = 3;
std::cout << "大于" << threshold << "的数: ";
std::for_each(vec.begin(), vec.end(), [threshold](int x) {
if (x > threshold) {
std::cout << x << " ";
}
});
std::cout << std::endl;
// Lambda排序
std::vector<std::pair<int, std::string>> pairs = {
{3, "three"}, {1, "one"}, {2, "two"}
};
std::sort(pairs.begin(), pairs.end(),
[](const auto& a, const auto& b) {
return a.first < b.first;
});
std::cout << "排序后: ";
for (const auto& p : pairs) {
std::cout << p.second << " ";
}
std::cout << std::endl;
}
5. 实用工具
#include <utility>
#include <tuple>
#include <memory>
void utility_example() {
// pair
std::pair<int, std::string> p1 = {1, "Alice"};
auto p2 = std::make_pair(2, "Bob");
std::cout << "p1: " << p1.first << ", " << p1.second << std::endl;
std::cout << "p2: " << p2.first << ", " << p2.second << std::endl;
// tuple
std::tuple<int, std::string, double> t1 = {1, "Apple", 2.5};
auto t2 = std::make_tuple(2, "Banana", 1.8);
std::cout << "t1: " << std::get<0>(t1) << ", "
<< std::get<1>(t1) << ", "
<< std::get<2>(t1) << std::endl;
// 智能指针
std::unique_ptr<int> ptr1 = std::make_unique<int>(42);
std::cout << "unique_ptr: " << *ptr1 << std::endl;
std::shared_ptr<int> ptr2 = std::make_shared<int>(100);
std::shared_ptr<int> ptr3 = ptr2; // 共享所有权
std::cout << "shared_ptr use_count: " << ptr2.use_count() << std::endl;
// 移动语义
std::vector<int> source = {1, 2, 3, 4, 5};
std::vector<int> dest = std::move(source);
std::cout << "移动后source大小: " << source.size() << std::endl;
std::cout << "移动后dest大小: " << dest.size() << std::endl;
}
综合示例
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <map>
// 学生信息结构
struct Student {
int id;
std::string name;
double score;
// 用于排序的比较函数
bool operator<(const Student& other) const {
return score > other.score; // 按分数降序
}
};
void student_management_system() {
std::vector<Student> students = {
{101, "Alice", 85.5},
{102, "Bob", 92.0},
{103, "Charlie", 78.5},
{104, "David", 88.0},
{105, "Eve", 95.5}
};
// 1. 按分数排序
std::sort(students.begin(), students.end());
std::cout << "学生成绩排名:\n";
for (const auto& student : students) {
std::cout << "ID: " << student.id
<< ", 姓名: " << student.name
<< ", 分数: " << student.score << std::endl;
}
// 2. 查找特定学生
auto it = std::find_if(students.begin(), students.end(),
[](const Student& s) { return s.name == "Charlie"; });
if (it != students.end()) {
std::cout << "\n找到Charlie,分数: " << it->score << std::endl;
}
// 3. 统计分数段
int high_score = std::count_if(students.begin(), students.end(),
[](const Student& s) { return s.score >= 90.0; });
std::cout << "\n90分以上人数: " << high_score << std::endl;
// 4. 计算平均分
double total = std::accumulate(students.begin(), students.end(), 0.0,
[](double sum, const Student& s) {
return sum + s.score;
});
double average = total / students.size();
std::cout << "平均分: " << average << std::endl;
// 5. 使用map按ID快速查找
std::map<int, Student> student_map;
for (const auto& student : students) {
student_map[student.id] = student;
}
int search_id = 102;
auto map_it = student_map.find(search_id);
if (map_it != student_map.end()) {
std::cout << "\n通过ID查找: " << map_it->second.name
<< ", 分数: " << map_it->second.score << std::endl;
}
}
int main() {
std::cout << "===== STL综合示例 =====\n" << std::endl;
// 运行各个示例
std::cout << "1. 容器示例:" << std::endl;
vector_example();
std::cout << std::endl;
std::cout << "2. 算法示例:" << std::endl;
algorithm_example();
std::cout << std::endl;
std::cout << "3. 函数对象和Lambda示例:" << std::endl;
functor_example();
std::cout << std::endl;
std::cout << "4. 学生管理系统示例:" << std::endl;
student_management_system();
return 0;
}
最佳实践
-
选择正确的容器:
-
需要随机访问:
vector、array -
频繁插入删除:
list、deque -
需要自动排序:
set、map -
需要快速查找:
unordered_set、unordered_map
-
-
使用算法代替手写循环:
// 不好 for (int i = 0; i < vec.size(); ++i) { if (vec[i] > threshold) { // 处理 } } // 更好 std::for_each(vec.begin(), vec.end(), [threshold](int x) { if (x > threshold) { // 处理 } }); -
使用智能指针管理资源:
// 避免 MyClass* obj = new MyClass(); // ... 使用obj delete obj; // 推荐 auto obj = std::make_unique<MyClass>(); // 自动释放内存 -
优先使用迭代器而不是索引:
// 可移植性更好 for (auto it = vec.begin(); it != vec.end(); ++it) { // 使用*it }
总结
STL是C++的核心特性之一,提供了强大而高效的工具集。掌握STL可以显著提高开发效率,写出更简洁、更安全、更高效的代码。建议通过实际项目不断练习,深入理解各个组件的特性和适用场景。