【STL 源码剖析】浅谈 STL 迭代器与 traits 编程技法 (4)

上述的过程是首先询问 iterator_traits::value_type,如果传递的 I 为指针,则进入特化版本, iterator_traits 直接回答T;如果传递进来的 I 为 class type ,就去询问 T::value_type。

通俗的解释可以参照下图:

【STL 源码剖析】浅谈 STL 迭代器与 traits 编程技法

总结:核心知识点在于 模板参数推导机制+内嵌类型定义机制, 为了能处理原生指针这种特殊的迭代器,引入了偏特化机制。traits 就像一台 “特性萃取机”,把迭代器放进去,就能榨取出迭代器的特性。

这种偏特化是针对可调用函数 func 的偏特化,想象一种极端情况,假如 func 有几百万行代码,那么如果不这样做的话,就会造成非常大的代码污染。同时增加了代码冗余。

【STL 源码剖析】浅谈 STL 迭代器与 traits 编程技法

7、迭代器的型别和种类 7.1 迭代器的型别

我们再来看看迭代器的型别,常见迭代器相应型别有 5 种:

value_type:迭代器所指对象的类型,原生指针也是一种迭代器,对于原生指针 int*,int 即为指针所指对象的类型,也就是所谓的 value_type 。

difference_type: 用来表示两个迭代器之间的距离,对于原生指针,STL 以 C++ 内建的 ptrdiff_t 作为原生指针的 difference_type。

reference_type: 是指迭代器所指对象的类型的引用,reference_type 一般用在迭代器的 * 运算符重载上,如果 value_type 是 T,那么对应的 reference_type 就是 T&;如果 value_type 是 const T,那么对应的reference_type 就是 const T&。

pointer_type: 就是相应的指针类型,对于指针来说,最常用的功能就是 operator* 和 operator-> 两个运算符。

iterator_category: 的作用是标识迭代器的移动特性和可以对迭代器执行的操作,从 iterator_category 上,可将迭代器分为 Input Iterator、Output Iterator、Forward Iterator、Bidirectional Iterator、Random Access Iterator 五类,这样分可以尽可能地提高效率。

template<typename Category, typename T, typename Distance = ptrdiff_t, typename Pointer = T*, typename Reference = T&> struct iterator //迭代器的定义 { typedef Category iterator_category; typedef T value_type; typedef Distance difference_type; typedef Pointer pointer; typedef Reference reference; };

iterator class 不包含任何成员变量,只有类型的定义,因此不会增加额外的负担。由于后面三个类型都有默认值,在继承它的时候,只需要提供前两个参数就可以了。这个类主要是用来继承的,在实现具体的迭代器时,可以继承上面的类,这样子就不会漏掉上面的 5 个型别了

对应的迭代器萃取机设计如下:

tempalte<typename I> struct iterator_traits {//特性萃取机,萃取迭代器特性 typedef typename I::iterator_category iterator_category; typedef typename I::value_type value_type; typedef typeanme I:difference_type difference_type; typedef typename I::pointer pointer; typedef typename I::reference reference; }; //需要对型别为指针和 const 指针设计特化版本看 7.2、迭代器的分类

最后,我们来看看,迭代器型别 iterator_category 对应的迭代器类别,这个类别会限制迭代器的操作和移动特性。
除了原生指针以外,迭代器被分为五类:

Input Iterator: 此迭代器不允许修改所指的对象,是只读的。支持 ==、!=、++、*、-> 等操作。

Output Iterator:允许算法在这种迭代器所形成的区间上进行只写操作。支持 ++、* 等操作。

Forward Iterator:允许算法在这种迭代器所形成的区间上进行读写操作,但只能单向移动,每次只能移动一步。支持 Input Iterator 和 Output Iterator 的所有操作。

Bidirectional Iterator:允许算法在这种迭代器所形成的区间上进行读写操作,可双向移动,每次只能移动一步。支持 Forward Iterator 的所有操作,并另外支持 – 操作。

Random Access Iterator:包含指针的所有操作,可进行随机访问,随意移动指定的步数。支持前面四种 Iterator 的所有操作,并另外支持 [n] 操作符等操作。

【STL 源码剖析】浅谈 STL 迭代器与 traits 编程技法

那么,这里,小贺想问大家,为什么我们要对迭代器进行分类呢?迭代器在具体的容器里是到底如何运用的呢?这个问题就放到下一节在讲。

最最后,我们再来回顾一下六大组件的关系:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wspdfd.html