前言: 在容器部分结束后其实是一些坑留下来的,比如 STACK、queue等容器,并没有介绍,但是并不是表示它们不重要,恰恰相反,他们代表的思想可能更加需要重视:
配接器的思想。
在学习设计模式的时候,我们就知道有一种设计模式叫装饰器模式:《Design Patterns》对 Adapter 设计模式的定义如下:将一个 class 的接口转换为另一个 class 的接口,使原本因接口不兼容而不能合作的 classes,可以一起运作。一言以蔽之,Adapter 用于改变接口。
一:配接器的种类
STL 主要提供如下三种配接器:
(1)改变仿函数(functors)接口,称之为 function adapter
(2)改变容器 (containers)接口,称之为 container adapter
(3)改变迭代器(iterators)接口者,称之为 iterator adapter
二:容器配接器
STL 提供的两个容器 queue 和 stack,其实都不过是一种配接器,是对 deque (双端队列)接口的修饰而成就自己的容器风貌。如果按照该标准衡量其他容器的话,序列式容器的 set 和 map 其实是对其内部所维护的 RB-tree 接口的改造:
(1)deque:stack、queue
(2)RB-tree:set、map
(所以在queue和stack中是没有迭代器的概念的)
三:迭代器配接器
可参考:http://blog.csdn.net/lanchunhui/article/details/50934242
改变迭代器接口。
<1>. Insert Iterator: 插入型迭代器适配器主要有三个--back_inserter(Container& x),front_inserter(Container& x),inserter(Container&x,Iterator i).
每一个插入型的迭代器适配器内部都维护着一个容器;容器拥有自己的迭代器,于是当客户端对插入型适配器执行赋值操作时会在适配器内部转换成对容器本身的操作,但若是容器本身没有提供相应的插入操作,则相应的插入型适配器不能用于此容器之上。(如因vector未提供front_insert操作,故front_inserter不能应用于vector,否则执行时会出错。)
<2>. Reverse iterators:逆序迭代器适配器,主要有rbegin(),rend()
迭代器必须是双向迭代器,并且其有begin(),end()方可使用此逆序迭代器适配器。一定要注意rbegin(),rend()与begin(),end()之间的关系。
<3>. IOStream Iterator: 输入输出流迭代器适配器
绑定到istream的迭代器具有输入功能
绑定到ostream的迭代器具有输出功能
四:函数配接器
functor adapters是所有配接器中数量最庞大的一个族群,其配接灵活度是后两者不能及的,可以配接、配接、在配接。其中配接操作包括系结(bind)、否定(negate)、组合(compose)、以及对一般函数或成员函数的修饰(使其成为一个仿函数)。它的价值在于,通过它们之间的绑定、组合、修饰能力,几乎可以无限制地创造出各种可能的表达式(expression),搭配STL算法一起演出。
由于仿函数就是“将function call操作符重载”的一种class,而任何算法接受一个仿函数时,总是在其演算过程中调用该仿函数的operator(),这使得不具备仿函数之形、却有真函数之实的“一般函数”和“成员函数(member functions)感到为难。如果”一般函数“和“成员函数”不能纳入复用的体系中,则STL的规划将崩落了一角。为此,STL提供了为数众多的配接器,使“一般函数”和“成员函数”得以无缝地与其他配接器或算法结合起来。
注意,所有期望获取配接能力的组件,本身都必须是可配接的,即一元仿函数必须继承自unary_function,二元仿函数必须继承自binary_function,成员函数必须以mem_fun处理过,一般函数必须以ptr_fun处理过。一个未经ptr_fun处理过的一般函数,虽然也可以函数指针的形式传给STL算法使用,却无法拥有任何配接能力。