《STL源码剖析》——迭代器(iterators)概念与traits编程技法(一)

一、迭代器设计思维——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;
};
        由于后三个参数皆有默认值,故新的迭代器只需提供前两个参数即可。





你可能感兴趣的:(C++,源代码,STL)