zoukankan      html  css  js  c++  java
  • Stl源码剖析 第三章 iterator摘要

    1. Stl的设计思想是: 将数据容器和算法分开,彼此独立设计,最后再以一贴胶合剂将它们撮合在一起,这个胶合剂就是迭代器。

    2. 从3.2节迭代器的实现可知,如果要设计一个与容器分离实现的迭代器,会暴露太多容器实现的细节,也就是说,要设计出针对某个容器的迭代器,必须对容器的实现细节非常了解,

    所以就将容器的实现细节交给容器设计者,专属迭代器的实现成为容器的一部分,所以每个Stl容器都有提供专属的迭代器。

    3. 迭代器是一种行为类似指针的对象,而指针的各种行为中最常见也最重要的便是内容提领和成员访问,因此,迭代器最重要的编程工作就是对 operator* 和 operator-> 进行重载。

    4. 函数 template参数推导机制只能推导参数,无法推导函数返回值的类型,为了解决这个问题,迭代器类要使用 typedef类型定义关键字,将其模板类型定义为一个固定的名字(value_type),

    然后函数返回值写成 typename T::value_type,即可告知编译器函数返回值是一个模板类型。 但这有一个局限,如果函数参数,即这个迭代器不是类类型,而是普通指针,typename T::value_type就没用了。

    解决办法,偏特化:对template参数再进行特化,即模板的模板。 具体实现是实现一个通用类,去萃取模板参数的类型。

    template <class I>
    struct iterator_traits
    {
        typedef typename I:value_type value_type;
    };
    

    如果迭代器类I有实现自己的value_type,即可萃取出来。

    对于普通指针,例如 int* 和 const int*  则要实现特化版本,如下:

     1  template <class T>
     2  struct iterator_traits<T*> //T* can trait int*
     3  {
     4      typedef T value_type;
     5  }   
     6  
     7  
     8  template <class T>
     9  struct iterator_traits<const T*> //const T* can trait const int*
    10  {
    11      typedef T value_type;
    12  }   

    所以关键是这个 iterator_traits,既可萃取迭代器类的value_type, 又可以萃取普通指针的类型。

    5. 每个迭代器要实现5种 typedef, 这个是根据STL算法实现而做出的结论:

    1). iterator_category(迭代器类型,5选1)

    2). value_type 所指向对象类型。 typedef T value_type    |     typedef Iterator<T> value_type

    3). difference_type 表示两个迭代器距离的类型,一般是 ptrdiff_t。

    4). pointer 所指向元素的指针类型   ==>  typedef T* pointer |  typedef Iterator<T>* pointer

    5). reference 所指向元素的引用类型   ==>  typedef T& reference  |  typedef Iterator<T>& reference

    其实迭代器类的typedef定义和普通指针的偏特化的typedef定义是类似的。

    对于iterator_category,是用class来定义的,虽然class没有内容,不仅可以促成重载机制的成功运作,另一个好处是,通过继承,可以不必再写“单纯只做传递调用”(if else)的函数。

    每个迭代器只需要形似:

    typedef random_access_iterator_tag:: iterator_category 即可定义自己的迭代器类型。

    算法在根据迭代器重载多个实现特化版本的时候,最后一个参数就是其中一个iterator_category class的类型。

    6. stl提供了一个iterator class定义,自己若是实现了一个容器,迭代器只需要继承这个iterator,重新定义Category 和 valye_type即可。

    总结:

      设计适当的关联类型(以上5种), 是迭代器本身的责任。设计适当的迭代器,则是容器的责任。 因为只有容器设计者才知道该设计出怎样的迭代器来访问自己,并执行迭代器应有的各种行为(++, --, *, ->)。 因此算法可以完全

    独立于容器和迭代器自行设计,对外提供迭代器参数接口即可。

    traits编程技法大量运用于STL实现品种,它利用“内嵌型别”的编程技巧与编译器的template参数推导功能,增强C++未能提供的关于型别认证方面的能力,弥补了C++不为强型别语言的遗憾。了解traits编程技法,就象获得“芝麻开门”的口诀一样,从此

    得以一窥STL源代码的奥秘。

    Coding Life
  • 相关阅读:
    SharePoint 2010 新体验3 文档集
    Firebird 修改表名
    C++Builder XE7 up1 简单测试
    Firbird 将可 null 的列更新为 not null
    用delphiXE7 dbExpress Framework提供的功能获取数据表信息
    Linux的基本命令总结
    IOS 隐藏时间条
    最大流 ZQUOJ 10181 && POJ 1273
    最大二分匹配 匈牙利算法模板&&POJ 1469 COURSES
    新加坡第四天下午
  • 原文地址:https://www.cnblogs.com/lewiskyo/p/6243245.html
Copyright © 2011-2022 走看看