概述
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可以显著提高开发效率,写出更简洁、更安全、更高效的代码。建议通过实际项目不断练习,深入理解各个组件的特性和适用场景。