一、迭代器设计思维——STL关键所在
STL的中心思想在于:将数据容器(containers)和算法(algorithms)分开,彼此独立设计,最后再以一帖粘合剂将它们撮合在一起。
二、迭代器(iterator)是一种 smart pointer
迭代器是一种行为类似指针的对象,而指针的各种行为中最常见也最重要的便是内容提领(dereference)和成员访问(member access),因此,迭代器最重要的编程工作就是对 operator* 和 operator-> 进行重载(overloading)工作。
每一种STL容器都提供有专属迭代器的缘故。
三、Traits编程技法——STL源代码门钥
若要 traits 能够有效运作,每一个迭代器必须遵循约定,自行以内嵌型别定义(nested typedef)的方式定义出相应型别(associated types)。根据经验,最常用到的迭代器相应型别有五类:value type,difference type,pointer,reference,iterator catagoly。
// "榨汁机"traits template <class Iterator> struct iterator_traits { typedef typename Iterator::iterator_category iterator_category; typedef typename Iterator::value_type value_type; typedef typename Iterator::difference_type difference_type; typedef typename Iterator::pointer pointer; typedef typename Iterator::reference reference; };
1. 迭代器相应型别之一:value type
value type,是指迭代器所指对象的型别。任何一个打算与STL算法有完美搭配的 class,都应该定义自己的value type内嵌型别。
2. 迭代器相应型别之二:difference type
difference type 用来表示两个迭代器之间的距离。针对相应型别 difference type,traits 的如下两个(针对原生指针而写的)特化版本,以C++内建的ptrdiff_t(定义于<cstddef>头文件)作为原生指针的difference type:
template<class Iterator> struct iterator_traits { ... typedef typename Iterator::difference_type difference_type; }; // 针对原生指针而设计的“偏特化(partial specialization)”版 template <class T> struct iterator_traits<T *> { ... typedef ptrdiff_t difference_type; }; // 针对原生的 pointer-to-const 而设计的“偏特化(partial specialization)”版 template <class T> struct iterator_traits<const T*> { ... typedef ptrdiff_t difference_type; };
3. 迭代器相应型别之三:reference type
4. 迭代器相应型别之四:pointer type
template<class Iterator> struct iterator_traits { ... typedef typename Iterator::pointer pointer; typedef typename Iterator::reference reference; }; // 针对原生指针而设计的“偏特化(partial specialization)”版 template <class T> struct iterator_traits<T *> { ... typedef T* pointer; typedef T& reference; }; // 针对原生的 pointer-to-const 而设计的“偏特化(partial specialization)”版 template <class T> struct iterator_traits<const T*> { ... typedef const T* pointer; typedef const T& reference; };
5. 迭代器相应型别之五:iterator_category
根据移动特性与施行操作,迭代器被分为五类:
a. Input Iterator:这种迭代器所指的对象,不允许外界改变。只读(read only)。
b. Output Iterator:唯写(write only)。
c. Forward Iterator:允许“写入型”算法在此种迭代器所形成的区间上进行读写操作。
d. Bidirectional Iterator:可双向移动。某些算法需要逆向走访某个迭代器区间,可以使用 Bidirectional Iterator。
e. Random Access Iterator:前四种迭代器都只供应一部分指针算术能力(前三种支持 operator++,第四种在加上 operator--),第五种则涵盖所有指针算术能力,包括 p+n, p-n, p[n], p1 - p2, p1 < p2。
四、std::iterator 的保证
为了符合规范,任何迭代器都应该提供五个内嵌相应型别,以利于 traits 萃取,否则便是自别于整个STL架构,可能无法与其它 STL 组件顺利搭配。STL 提供了一个 iterators class 如下,如果每个新设计的迭代器都继承自它,就可保证符合 STL 所需之规则:
template <class Category, class T, class Distance = ptrdiff_t, class Pointer = T*, class Reference = T&> struct iterator { typedef Category iterator_category; typedef T value_type; typedef Distance difference_type; typedef Pointer pointer; typedef Reference reference; };由于后三个参数皆有默认值,故新的迭代器只需提供前两个参数即可。