C++ STL概述
什么是STL?
STL(Standard Template Library,标准模板库)是C++标准库的一部分,提供了一系列通用的模板类和函数,这些模板类和函数可以实现许多常用的数据结构和算法,如向量、链表、队列、栈、集合、映射、排序、搜索等。
STL的设计理念是将数据和操作分离,通过模板技术实现,具有高度的可复用性、可扩展性和效率。通过使用STL,程序员可以避免重复"发明轮子",专注于解决应用问题。
STL的核心组件
STL主要由以下六大组件构成:
1. 容器(Containers)
容器是用来存储数据的模板类,分为三类:
-
顺序容器:按照线性顺序存储元素
vector
:动态数组list
:双向链表deque
:双端队列array
(C++11):固定大小数组forward_list
(C++11):单向链表
-
关联容器:基于键值对快速查找
set
:集合(不重复元素)map
:映射(键值对)multiset
:可重复元素集合multimap
:可重复键映射
-
无序容器(C++11):基于哈希表实现
unordered_set
:无序集合unordered_map
:无序映射unordered_multiset
:无序可重复集合unordered_multimap
:无序可重复映射
2. 算法(Algorithms)
STL提供了大量的算法用于处理容器中的数据,这些算法以函数模板形式实现,常见的有:
- 非修改序列操作:
find
、count
、for_each
等 - 修改序列操作:
copy
、move
、transform
等 - 排序相关:
sort
、merge
、partition
等 - 数值操作:
accumulate
、inner_product
等
3. 迭代器(Iterators)
迭代器提供了访问容器元素的统一接口,是算法和容器之间的桥梁。按功能分类:
- 输入迭代器:只读,只能向前移动一次
- 输出迭代器:只写,只能向前移动一次
- 前向迭代器:可读写,可多次向前移动
- 双向迭代器:可读写,可向前向后移动
- 随机访问迭代器:可读写,可随机访问
4. 函数对象(Function Objects)
函数对象是行为类似函数的对象,可以被当做算法的参数。
5. 适配器(Adapters)
适配器用于转换容器、迭代器或函数对象的接口。常见的容器适配器有:
stack
:栈适配器queue
:队列适配器priority_queue
:优先队列适配器
6. 分配器(Allocators)
分配器负责空间的分配和管理,用户通常不需要直接操作分配器。
如何使用STL
要使用STL,你需要包含相应的头文件:
#include <vector> // 使用vector容器
#include <list> // 使用list容器
#include <map> // 使用map容器
#include <algorithm> // 使用算法
#include <iterator> // 使用迭代器
#include <functional>// 使用函数对象
STL容器基础示例
使用vector容器
#include <iostream>
#include <vector>
int main() {
// 创建一个整数vector
std::vector<int> numbers;
// 添加元素
numbers.push_back(10);
numbers.push_back(20);
numbers.push_back(30);
// 使用索引访问
std::cout << "第二个元素: " << numbers[1] << std::endl;
// 使用迭代器遍历
std::cout << "所有元素: ";
for (auto it = numbers.begin(); it != numbers.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 使用范围for循环 (C++11)
std::cout << "使用范围for: ";
for (auto num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
输出:
第二个元素: 20
所有元素: 10 20 30
使用范围for: 10 20 30
使用map容器
#include <iostream>
#include <map>
#include <string>
int main() {
// 创建一个字符串到整数的映射
std::map<std::string, int> ages;
// 插入键值对
ages["Alice"] = 30;
ages["Bob"] = 25;
ages.insert(std::make_pair("Charlie", 35));
// 查找和访问
std::cout << "Bob的年龄: " << ages["Bob"] << std::endl;
// 检查键是否存在
if (ages.find("David") == ages.end()) {
std::cout << "David不在map中" << std::endl;
}
// 遍历所有键值对
std::cout << "所有人的年龄: " << std::endl;
for (const auto& pair : ages) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}
输出:
Bob的年龄: 25
David不在map中
所有人的年龄:
Alice: 30
Bob: 25
Charlie: 35
STL算法示例
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {30, 10, 50, 20, 40};
// 排序
std::sort(numbers.begin(), numbers.end());
std::cout << "排序后: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// 查找元素
auto it = std::find(numbers.begin(), numbers.end(), 20);
if (it != numbers.end()) {
std::cout << "找到元素20,位置: "
<< (it - numbers.begin()) << std::endl;
}
// 计算总和
int sum = std::accumulate(numbers.begin(), numbers.end(), 0);
std::cout << "总和: " << sum << std::endl;
return 0;
}
输出:
排序后: 10 20 30 40 50
找到元素20,位置: 1
总和: 150
备注
要使用accumulate
函数,需要包含<numeric>
头文件。上面的例子中省略了这一包含语句。