迭代器作用
STL中,算法和容器是分开的,彼此独立,通过迭代器联系在一起
迭代器的设计,就是为了在不暴露容器的内部表达式的前提下让算法能够遍历容器的各个元素
traits技法的引出
迭代器是一种类似指针的对象,最重要的便是对operator *和operator ->进行重载,为了让迭代器适用于任何型态的结点,需要把它设计为class template
在算法中运用迭代器,很可能会用到其相应型别,而C++之支持sizeof( ),并未支持typeof( ),即便动用RTTI性质中的typeid( ),获得的也只是型别的别名,不能用来当变量声明用
解救的办法有几个
①利用function template的参数推导机制
但是,template参数推导机制推导的只是参数,无法推导返回值型别,所以只能采用声明内嵌型别的方法
看起来不错,但却有个陷阱:并非所有的迭代器都是class type,原生指针就不是,如果不是class type,就无法在类中定义内嵌型别,所以上面这样还不够,还需要引入trait技法
②traits技法
不通过声明内嵌型别,而是直接采用另外一个类来把迭代器的型别给提取出来
traits中通过类的偏特化(partial specialization)特性,可以将原生指针偏特化,这样就弥补了上面无法识别原生指针的缺点
详细见:https://blog.csdn.net/qq100440110/article/details/51854673
最常见的迭代器型别有5种value_type、difference_type、pointer、reference、iterator_category,因此traits中会有这5个类型
我们直接把原生指针或迭代器扔进traits中,便可得到对应的型别
迭代器相应型别
- value_type:所指对象的型别
- difference_type:两个迭代器之间的距离
- reference type与pointer type(见下图)
- iterator_category:迭代器种类
根据迭特性与施行操作,迭代器被分为五类:
- Input Iterator:这种迭代器所指对象,不允许外界改变。只读(read only)。
- Output Iterator:唯写(write only)。
- Forward Iterator:允许「写入型」算法(例如 replace() )在此种迭代器所形成的区间上做读写动作。
- Bidirectional Iterator:可双向移动。某些算法需要逆向走访某个迭代器区间(例如逆向拷贝某范围内的元素),就可以使用 Bidirectional Iterators。
- Random Access Iterator:前四种迭代器都只供应一部份指标算术能力(前三种支持 operator++ ,第四种再加上 operator-- ),第五种则涵盖所有指标算术能力,包括 p+n, p-n, p[n], p1-p2, p1<p2
它们之间的继承关系如下,Output Iterator独立开来
iterator的保证
为符合规范,任何迭代器都应该提供5个内嵌相应型别,以利于traits的萃取,实际实现中,STL提供了一个iterator class,每个迭代器都继承自它,就可保证符合规范
iterator class 不含任何成员,纯粹只是型别定义,所以继承它并不会招致任何额外负担。由于后三个参数皆有默认值,新的迭代器只需提供前两个参数即可