如果说C++的基础语法是英雄的筋骨,那么标准模板库(STL)就是英雄手中威力无穷的神兵利器。STL提供了一套经过千锤百炼的通用组件,主要包括容器、算法和迭代器。熟练运用STL,能让你从重复造轮子的苦役中解放出来,专注于解决更核心的问题,极大提升编程效率和代码质量。
第一部分:容器------数据的智能仓库
容器用于存储和管理数据集合。不同的容器有不同的特性和适用场景。
-
序列式容器:
std::vector
(动态数组)
vector
是最常用的容器,它在堆上分配连续内存,支持快速随机访问(O(1)时间复杂度)。其大小可以动态增长。cpp
复制下载
c#include <vector> #include <iostream> void vectorDemo() { std::vector<int> nums = {1, 2, 3, 4, 5}; // 初始化列表 // 1. 遍历 (C++11 范围for循环) std::cout << "元素: "; for (int num : nums) { std::cout << num << " "; } std::cout << std::endl; // 2. 添加元素 nums.push_back(6); // 在末尾添加 nums.insert(nums.begin() + 2, 99); // 在索引2的位置插入99 // 3. 访问元素 std::cout << "第一个元素: " << nums.front() << std::endl; std::cout << "最后一个元素: " << nums.back() << std::endl; std::cout << "索引为3的元素: " << nums[3] << std::endl; // 不检查越界 std::cout << "索引为3的元素: " << nums.at(3) << std::endl; // 检查越界,越界则抛出异常 // 4. 删除元素 nums.pop_back(); // 删除末尾元素 nums.erase(nums.begin() + 1); // 删除索引1的元素 std::cout << "操作后: "; for (auto it = nums.begin(); it != nums.end(); ++it) { // 使用迭代器 std::cout << *it << " "; } std::cout << std::endl; }
-
关联式容器:
std::map
(键值对集合)
map
基于红黑树实现,存储的是key-value
键值对,并且key
是自动排序的。它支持通过key
快速查找对应的value
(O(log n)时间复杂度)。cpp
复制下载
c#include <map> #include <string> void mapDemo() { std::map<std::string, int> studentScores; // 插入数据 studentScores["Alice"] = 95; studentScores["Bob"] = 87; studentScores["Charlie"] = 92; studentScores.insert({"David", 78}); // 遍历 (map的每个元素是一个std::pair) for (const auto& pair : studentScores) { std::cout << pair.first << " 的分数是: " << pair.second << std::endl; } // 查找数据 std::string name = "Bob"; auto it = studentScores.find(name); if (it != studentScores.end()) { std::cout << "找到了 " << name << ", 分数: " << it->second << std::endl; } else { std::cout << "没有找到 " << name << std::endl; } // 使用下标访问(如果key不存在,会创建一个新条目) std::cout << "Alice的分数: " << studentScores["Alice"] << std::endl; }
第二部分:算法与迭代器------解耦的艺术
STL算法的强大之处在于,它们通过迭代器与容器解耦。迭代器是泛化的指针,用于遍历容器中的元素。算法不关心操作的是哪种容器,只关心迭代器提供的访问接口。
示例:使用std::sort
和std::find_if
cpp
复制下载
c
#include <algorithm>
#include <vector>
#include <iostream>
bool isOdd(int n) {
return n % 2 != 0;
}
void algorithmDemo() {
std::vector<int> data = {5, 2, 8, 1, 9, 3};
// 1. 排序 (默认升序)
std::sort(data.begin(), data.end());
std::cout << "升序排序: ";
for (int x : data) std::cout << x << " ";
std::cout << std::endl;
// 降序排序
std::sort(data.begin(), data.end(), std::greater<int>());
std::cout << "降序排序: ";
for (int x : data) std::cout << x << " ";
std::cout << std::endl;
// 2. 查找第一个满足条件的元素
auto oddIt = std::find_if(data.begin(), data.end(), isOdd);
if (oddIt != data.end()) {
std::cout << "找到第一个奇数: " << *oddIt << ",位于索引 " << (oddIt - data.begin()) << std::endl;
}
// 3. 使用Lambda表达式(更现代的方式)
auto evenIt = std::find_if(data.begin(), data.end(), [](int n) { return n % 2 == 0; });
if (evenIt != data.end()) {
std::cout << "找到第一个偶数: " << *evenIt << std::endl;
}
// 4. 计数
int countOfOdd = std::count_if(data.begin(), data.end(), isOdd);
std::cout << "奇数的个数: " << countOfOdd << std::endl;
}
结论:
STL将数据结构和算法分离,通过迭代器桥接,实现了高度的通用性和效率。作为一名C++程序员,你的目标不应该是自己实现一个链表或排序算法,而是深刻理解每种STL容器的特性和算法的用途,从而在面对问题时,能迅速选出最合适的"工具",组合出优雅高效的解决方案。这才是STL赋予"英雄C++"程序员的真正力量。