众所周知STL是C++的标准模板库,功能及其强大,深受大家的喜爱。多说一句听说python,已经登顶称王了。而我还在学远古级编程语言C++,实在是心痛啊。其实我本来是打算学pyhton的。
STL具有公共的接口,却又有不同的实现版本,HP版本是所有STL实现版本的始祖,后续的有比如:PJ,SGI,RW版本。各个版本的内部实现不同但是都具有相同的方法。简单地说,STL是一组模板类和函数,向程序人员提供了:
- 用于存储信息的容器
- 用于访问容器存储信息的迭代器
- 用于操作容器的算法
传说中的STL六大组件:容器,算法,迭代器,仿函数,配接器,配置器。其中它们的交互关系:容器通过配置器取得数据存储的空间,算法通过迭代器存取容器的内容,仿函数可以协助算法完成不同策略的变化,配接器可以修饰或是套接仿函数。
STL容器
容器是用于存储的STL类,STL提供了两种类型的容器:
- 顺序容器
- 关联容器
另外,STL还提供了被称为容器适配器(Container Adapter)的类,它们是顺序容器和关联容器的变种,包含的功能有限,用于满足特殊的需求。STL的一条不成文规定:不论底层是什么结构,在插入时总会插入到定位元素的前面。
顺序容器:
- std::vector:操作与动态数组一样,在最后插入数据。
- std::deque:与std::vector类似,但允许在开头插入或删除元素
- std::list:操作与双向链表一样,可将它视为链条,对象被连接在一起,你可以在任意位置添加或者删除对象
- std::forward_list:类似于std::list,但是单向链表,只能沿一个方向遍历
这里的vector和list大家都可以对比数据结构的内容来进行学习
关联容器:
关联容器按指定的顺序存储数据,就像词典一样。这将降低插入数据的速度,但在查询方面具有很大优势。
- std::set:存储各不相同的值,在插入时进行排序;容器的复杂度为对数
- std::unordered_set:存储各不相同的值,在插入时进行排序;容器的复杂度为对数。这种容器是C++11新增的
- std::map:存储键-值对,并根据唯一的键排序;容器的复杂度为对数
- std::unordered_map:存储键-值对,并根据唯一的键排序;容器的复杂度为对数。这种容器是C++11新增的
- std::multiset:与set类似,但允许存储多个值相同的项,即值不需要是唯一的
- std::unordered_multiset:与unordered_set类似,但允许存储多个值相同的项,即值不需要是唯一的。这种容器是C++11新增的
- std::multimap:与map类似,但不要求键是唯一的
- std::unordered_multimap:与unordered_map类似,但不要求键是唯一的。这种容器是C++11新增的。
容器的复杂度是一种指标,复杂度为常量的话,容器的性能和不受元素个数的影响;复杂度为对数的话,容器包含1000000个元素时,处理时间为1000个元素的两倍;复杂度为线性的话,容器包含1000000个元素时,处理时间为1000个元素的1000倍。
可以通过谓词函数编程定制STL容器的排序标准。
容器适配器:
- std::stack:以LIFO(后进先出)的方式存储元素,让你能够在栈顶插入(压入)和删除(弹出)元素
- std::queue:以FIFO(先进先出)的方式存储元素,让你能够删除最先插入的元素
- std::priority_queue:以特定的顺序存储元素,因为优先级最高的元素总是位于队列开头
STL迭代器
最简单的迭代器就是指针。给定一个指向数组中第一个元素的指针,可以递增该指针使其指向下一个元素,还可以直接对当前位置的模板进行操作。
STL中的迭代器是模板类,从某种程度上说它是泛型指针。迭代器是容器和算法之间的一座桥梁,也就是粘合剂。一般来说算法是模板函数,而容器是模板类。
STL提供的迭代器分为两大类:
- 输入迭代器:通过对输入迭代器解除引用,它将引用对象,而对象可能位于集合之中。最严格的的输入迭代器确保以只读的方式访问对象。
- 输出迭代器:输出迭代器让程序员对集合执行写入操作。最严格的输出迭代器确保只能执行写入操作。
上述两种基本迭代器可进一步分为三类:
- 前向迭代器:通常用于单向链表,是输入迭代器和输出迭代器的细化,它允许输入输出,前向迭代器可以是const的,只能读取它指向的对象;也可以改变对象,即可读写对象。
- 双向迭代器:通常用于双向链表,是前向迭代器的一种细化,可对其执行递减操作,从而向后移动。
- 随机访问迭代器:通常用于数组,是对双向迭代器的一种细化,可将其加减一个偏移量,还可将两个迭代器相减以得到集合中两个元素的相对距离。
PS:从实现层吗来说,可将“细化”视为继承或是具化。
STL算法
查找、排序和反转等都是标准的编程需要,不应该让程序员重复实现这样的功能。常见的STL算法如下所示。
- std::find:在集合中查找值
- std::find_if:根据用户指定谓词在集合中查找值
- std::reverse:反转集合中元素的排列顺序
- std::remove_if:根据用户指定的谓词将元素从集合中删除
- std::transform:使用用户定义的变化函数对容器中的元素进行变换
这些函数都是std命名空间中的模板函数,要使用它们,必须包含标准头文件<algorithm>。