目录
- 什么是 STL
- STL 的组成
- 迭代器
- 常用容器
- 算法
- 函数对象
什么是 STL
STL ( The C++ Standard Template Library ),C++标准模板库,是一个算法、数据结构和其他组件的集合,可用于简化C++程序的开发。STL提供了一系列的 容器 (container),如 vector、list、map,以及搜索、排序和操作数据的 算法 (algorithm)。
STL的主要优点之一是它提供了一种编写通用的、可重复使用的代码的方法,可以应用于不同的数据类型。这意味着,你可以一次写好一个算法,然后将其用于不同类型的数据,而不必为每种类型单独写代码。
STL 的组成
- 容器 (Container): STL 提供了一系列的容器,如 vector、list、map、set 和 stack 等,它们可以用来存储和操作数据。
- 算法 (Algorithm): STL 提供了一系列的算法,比如 sort、find 和 binary_search,这些算法可以用来操作存储在容器中的数据。
- 迭代器(Iterator): 迭代器是提供遍历容器中元素的方法的对象。STL提供了一系列的迭代器,比如前向迭代器 (forward iterator)、双向迭代器 (bidirectional iterator) 和随机访问迭代器 (random access iterator),它们可以与不同类型的容器一起使用。
- 函数对象(Function objects): 函数对象,也被称为functors,是可以作为算法的函数参数使用的对象。它们提供了一种将函数传递给算法的方法,允许你自定义其行为。
- 分配器(Allocator):分配器是一种用于管理内存分配和释放的工具。
- 适配器(Adapter):适配器是一种用于在现有的容器或迭代器(或上面其他组件,没有算法适配器)上添加新功能的工具,其本质还是容器和迭代器。
迭代器
常用的迭代器包括:输入迭代器(Input Iterator)、输出迭代器(Output Iterator)、前向迭代器(Forward Iterator)、双向迭代器(Bidirectional Iterator)、随机访问迭代器(Random Access Iterator)5种。输入迭代器和输出迭代器,它们不是把数组或容器当做操作对象,而是把输入流/输出流作为操作对象。这里简单介绍后面3种迭代器。
- 前向迭代器
前向迭代器支持以下运算:
运算 | 说明 |
---|---|
* | 解引用,得到迭代器指向元素的值 |
++it | 前置递增,将迭代器指向下一个元素 |
it++ | 后置递增,将迭代器指向下一个元素,并返回指向当前元素的迭代器副本 |
==,!= | 比较两个迭代器是否相等 |
- 双向迭代器
双向迭代器支持以下运算:
运算 | 说明 |
---|---|
* | 解引用,得到迭代器指向元素的值 |
++it | 前置递增,将迭代器指向下一个元素 |
it++ | 后置递增,将迭代器指向下一个元素,并返回指向当前元素的迭代器副本 |
–it | 前置递减,将迭代器指向前一个元素 |
it– | 后置递减,将迭代器指向前一个元素,并返回指向当前元素的迭代器副本 |
==,!= | 比较两个迭代器是否相等 |
- 随机访问迭代器
随机访问迭代器则支持更多的运算:
运算 | 说明 |
---|---|
* | 解引用,得到迭代器指向元素的值 |
++it | 前置递增,将迭代器指向下一个元素 |
it++ | 后置递增,将迭代器指向下一个元素,并返回指向当前元素的迭代器副本 |
–it | 前置递减,将迭代器指向前一个元素 |
it– | 后置递减,将迭代器指向前一个元素,并返回指向当前元素的迭代器副本 |
==、!=、<、<=、>、>= | 关系运算,用于比较两个迭代器的大小关系 |
it + n | 加法,用于将迭代器向前移动 n 个元素 |
it1 - it2 和 it - n | 减法,用于计算两个迭代器之间的距离,或将迭代器向后移动 n 个元素 |
it [ n ] | 返回指向 it 后面第 n 个位置的元素的引用 |
- 实现一个简单的迭代器:
template <typename T>
class ArrayIterator {
public:ArrayIterator(T* ptr) : ptr_(ptr) {}T& operator*() const {return *ptr_;}T* operator->() const {return ptr_;}ArrayIterator& operator++() {++ptr_;return *this;}ArrayIterator& operator--() {--ptr_;return *this;}
private:T* ptr_;
};int main() {int my_array[] = {1, 2, 3, 4, 5};ArrayIterator<int> it(my_array); // 创建一个迭代器for (; it != ArrayIterator<int>(my_array + 5); ++it) {std::cout << *it << " "; // 输出数组元素}return 0;
}
常用容器
容器类型 | 说明 |
---|---|
序列式容器(Sequence containers) | 这种容器按照元素在容器中的位置存储元素,可以按照索引访问元素。包括 vector 、deque 、list 、forward_list 和 array |
关联式容器(Associative containers) | 这种容器按照元素的键值存储元素,可以按照键值进行查找和访问元素,查找效率高。包括 set 、map 、multiset 和 multimap |
无序关联式容器(Unordered associative containers) | 这种容器也是按照元素的键值存储元素,但是它们使用哈希表来存储元素,因此它们不保证元素的顺序,另外容器的查找效率高。包括 unordered_set 、unordered_map 、unordered_multiset 和 unordered_multimap |
容器适配器(Container adapters) | 这种容器是对其他容器的封装,提供了不同的接口。包括 stack 、queue 和 priority_queue |
- 不同容器支持的迭代器不一样,主要是和容器的功能有关:
容器 | 对应的迭代器类型 |
---|---|
array | 随机访问迭代器 |
vector | 随机访问迭代器 |
deque | 随机访问迭代器 |
list | 双向迭代器 |
set / multiset | 双向迭代器 |
map / multimap | 双向迭代器 |
forward_list | 前向迭代器 |
unordered_map / unordered_multimap | 前向迭代器 |
unordered_set / unordered_multiset | 前向迭代器 |
其中,容器适配器因为其只是用于完成特殊的功能(先进先出 FIFO,后进先出LIFO)而不使用迭代器。在每个容器中,可以使用成员函数 begin( ) 获取对应的迭代器。
算法
STL 实现了数据结构与算法的分离,不需要在每个容器中单独地实现排序,查找什么的算法。通过迭代器可以将算法运用在不同的容器中,这也是迭代器的重要作用之一。这些算法也适用于普通数组。
#include <algorithm>
#include <iostream>int main() {int my_array[] = {5, 2, 1, 7, 4};std::sort(my_array, my_array + 5);//默认升序for (int i = 0; i < 5; ++i) {std::cout << my_array[i] << " ";}return 0;
}
函数对象
简单来说就是实现了 ( ) 运算符重载的类,这个类的实例对象就是一个函数对象。在使用这个对象时看上去像函数调用,而实际也执行了函数调用,所以叫做函数对象。
template<typename T>
class plus{
public:T operator()(const T a, const T b){return a+b;}
};
int main() {plus<int> a;std::cout << a(1,2) <<std::endl; // 3return 0;
}
STL 函数对象类模板:
std::less
和std::greater
:这些模板用于比较两个值的大小。std::less
返回true
如果第一个参数小于第二个参数,而std::greater
则返回true
如果第一个参数大于第二个参数。
int a = 5, b = 10;
std::less<int> less_than;
std::greater<int> greater_than;
bool result1 = less_than(a, b); // result1 = true
bool result2 = greater_than(a, b); // result2 = false
std::plus
和std::minus
:这些模板用于执行加法和减法运算。
int a = 5, b = 10;
std::plus<int> add;
std::minus<int> subtract;
int result1 = add(a, b); // result1 = 15
int result2 = subtract(a, b); // result2 = -5
std::multiplies
和std::divides
:这些模板用于执行乘法和除法运算。
int a = 5, b = 10;
std::multiplies<int> multiply;
std::divides<int> divide;
int result1 = multiply(a, b); // result1 = 50
int result2 = divide(a, b); // result2 = 0