0
点赞
收藏
分享

微信扫一扫

STL 迭代器

color_小浣熊 2022-05-04 阅读 86
c++

迭代器是一种行为类似指针的对象。迭代器最重要的工作是operator*、operator ->、operator ++。

每一种STL容器都提供专属迭代器。

2.1 迭代器相应类型概念、应用场景 & 偏特化概念
在实际的算法中,在运用迭代器时,会用到迭代器所指对象中的相应类型(associate type)。

那么算法实现中该如何满足 声明一个以“迭代器所指对象(中)的类型”为类型的成员/参数,或返回值是“迭代器所指对象(中)的类型”的类型 的需求呢?

可分为以下三种情况:

① 迭代器所指对象是c++内置类型;
② 迭代器所指对象是自定义类型(class type)情形;
③ 迭代器所指对象是原生指针(naive pointer)情形;
对应的运用以下三种方法解决:

① function template的参数推导(augument deducation)机制 ;
② 声明内嵌类型 ;
③ 利用泛化中偏特化(partial secification)(下面有解释) ;
envolve to :萃取机 iterator_traits 机制
注意:这三种方法是逐步整合为最终的实现的方案就是 iterator_traits萃取机 机制,它包含了函数模板的参数推导,声明内嵌类型和偏特化所有内容,也同时解决了以上的三个场景的实现需求。

 

偏特化(template partial specification):如果class template拥有一个以上的template参数,可以对其中某个(或数个,但非全部)template进行特化工作,其中偏特化有两种形式:

1. 对template参数的部分个参数进行特化;
2. 对template参数的范围进行限定;
两种形式见下图所示:

 

偏特化其实就可以理解为“针对任何template参数进一步地进行条件限制所设计出的特化版本”。那么对应的,全特化(full specification) 就是指对模板参数不做任何限制。

如上,利用对(常量)指针类型的偏特化,解决了内嵌类型无法解决的迭代器所指对象是原生指针类型的问题。


最终设计出了迭代器萃取机这一中间层,其作用是萃取出迭代器的相关特性(也即是相应类型的取用),以屏蔽迭代器实现对算法实现的影响。如左下图所示

 

 

在图中列出了原生指针(pointer),还单独列出了常量指针(pointer-to-const)(对于const关键字的解析见:const限定符)。对于常量指针,泛化版本的iterator::traits<const int*> value_type会返回一个const int,也即返回值是一个无法进行赋值的临时变量,所以针对常量指针的value_type类型应当特化为非常量类型,如下
 

template <class T>
struct iterator_traits<const T*> { //偏特化版本——当迭代器是一个pointer-to-const时
	typedef T value_type;          //萃取出的类型应当是T而非常量const T
	//...
};

//附上指针的偏特化萃取实现
struct iterator_traits<T*> {
	typedef T value_type;
	//...
};

所以只要迭代器的实现者在实现过程中,将内嵌类型和原生类型遵循约定,以内嵌类型(nested typedef)的方式定义(typedef)出STL迭代器萃取机所规定的相关类型,就可以与STL标准实现兼容,实现算法实现和容器实现的剥离。

如右上图(iterator_traits对常用内嵌类型的typedef)所示,迭代器中最常用到的迭代器类型有五种,整理出如下表格:

迭代器相关类型    说明
value_type    所谓value type,指的是迭代器所指对象的类型。任何一个与STL有完美搭配的class,都应该定义value type内嵌类型
difference_type    difference type表示两个迭代器之间的距离,因此也可用来表示一个容器的最大容量(头尾距离),以alogrithm中的count()为例:

对于原生指针,c++内建了ptrdiff_t(位于<cstddef>头文件内)作为原生指针的difference type(在iterator_traits<(const) T*>中使用);
当需要迭代器I的difference type,可以写typename iterator_traits<I>::difference_type,如上图中例;
reference    首先根据迭代器能否更改所指的对象,可以分为constant iterators和mutable iterators两种;
对应两种迭代器:
如果iterator是const的,那么若是其value_type是T,那么返回值应当是const T&;
如果iterator是mutable的,那么若是其value_type是T,那么返回值应当为T&;
pointer    指向迭代器所指之物/对象的类型的指针的类型;
iterator_category    对于迭代器种类,若是良好的利用好category的继承关系,可以极大地提高算法的效率,种类的具体解释和继承关系如下面图中所示。以advance()函数为例可以探讨category对算法的影响,详细内容见《STL源码剖析》p93,运用到了类的多态性,向上类型转换(派生类转基类,is-a继承关系)。

符合规范,任何迭代器都应提供五个内嵌相应类别,以利于traits萃取。STL为此提供了一个iterators class,也即std::iterator如下,如果每个新设计的迭代器继承自它,就可保证STL所需之规范:


————————————————

 

举报

相关推荐

0 条评论