STL提供六大组件,彼此可以相互套用:
1、容器(Container)
各种数据结构,包括Vector、list、deque、set、map等等,是日常使用中比较常用的部分
容器 | 特性 | 所在头文件 |
向量 vector | 可以用常数时间访问和修改任意元素,在序列尾部进行插入和删除时,具有常数时间复杂度,对任意项的插入和删除就有的时间复杂度与到末尾的距离成正比,尤其对向量头的添加和删除的代价是惊人的高的 | <vector> |
双端队列 deque | 基本操作与向量相同,唯一的不同是,其在序列头部插入和删除操作也具有常量时间复杂度 | <deque> |
表 list | 对任意元素的访问与对两端的距离成正比,但对某个位置上插入和删除一个项的花费为常数时间。 | <list> |
队列 queue | 插入只可以在尾部进行,删除、检索和修改只允许从头部进行。按照先进先出的原则。 | <queue> |
堆栈 stack | 堆栈是项的有限序列,并满足序列中被删除、检索和修改的项只能是最近插入序列的项。即按照后进先出的原则 | <stack> |
集合 set | 由节点组成的红黑树,每个节点都包含着一个元素,节点之间以某种作用于元素对的谓词排列,没有两个不同的元素能够拥有相同的次序,具有快速查找的功能。但是它是以牺牲插入删除操作的效率为代价的 | <set> |
多重集合 multiset | 可以支持重复元素的set | <set> |
映射 map | 由{键,值}对组成的集合,以某种作用于键对上的谓词排列。具有快速查找能力 | <map> |
多重集合 multimap | 一个键可以对应多个值的map | <map> |
2、算法(Algorithm)
一些常用算法的实现,包括sort、merge、search、copy、erase等等;还有一些数学上的常用算法,包括一些加法乘法常用的函数;需要注意的一点是容器有一些自带的算法,在使用容器时,容器自带的算法优先级是要高于Algorithm的;
3、迭代器(Iterator)
迭代器是一种泛型对象,可以视为一种指针,可以通过迭代器指向容器中的某个元素,就可以对其进行读写。
4、仿函数(Function object)
行为类似函数,作为算法的某种策略。仿函数是泛型编程强大威力和纯粹抽象概念的又一例证。可以说,任何东西,只要其行为像函数,它就是一个函数。因此如果定义了一个对象,行为像函数,它就可以被当做函数来用。简单理解就是:一种比较简单的、主要用到operator()操作的、其他成员函数和成员变量都是为operator()服务的对象。
5、适配器(Adaptor)
适配器是用来修改其他组件接口的STL组件,是带有一个参数的类模板(这个参数是操作的值的数据类型)。改变 functors接口者,称为function adapter;改变 container 接口者,称为container adapter;改变iterator接口者,称为iterator adapter。
例如:STL提供的queue 和 stack,虽然看似容器,但其实只能算是一种容器配接器,因为它们的底部完全借助deque,所有操作都由底层的deque供应。
迭代器适配器:修改为某些基本容器定义的迭代器的接口的一种STL组件。反向迭代器和插入迭代器都属于迭代器适配器,迭代器适配器扩展了迭代器的功能。
函数适配器:通过转换或者修改其他函数对象使其功能得到扩展。这一类适配器有否定器(相当于"非"操作)、绑定器、函数指针适配器。函数对象适配器的作用就是使函数转化为函数对象,或是将多参数的函数对象转化为少参数的函数对象。
6、空间配置器(allocator)
空间配置器为容器分配并管理内存,统一的内存管理使得STL库的可用性、可移植行、以及效率都有了很大的提升。从实现的角度来看,配置器一种是实现了动态空间配置、空间管理、空间释放的class template,而另一种设计到小块内存的管理等,运用了内存池技术等。
这六大组件的交互关系:
container(容器) 通过 allocator(空间配置器) 取得\释放数据储存空间,algorithm(算法)通过 iterator(迭代器)存取 container(容器) 地址内容,functor(仿函数) 协助 algorithm(算法) 完成不同的策略变化,adapter(配接器) 可以修饰或套接 functor(仿函数)。
相关资料参考:
《STL源码剖析》 侯捷著
《C++标准程序库》 侯捷译