STL源码--iterator

  iterator,是stl中至关重要的一个组件,它是stl的基石,对于所有与容器有关的操作,几乎都用到iterator,本文先不谈iterator的各种使用技巧,而是谈谈iterator中的技术:

技术一:标记

//首先是迭代器的类型,我们需要一种方法来标记迭代器的类型,标记的方法多种多样,最简单的是使用掩码(宏定义)
//这里我们为什么不使用一个int或者unsigned来存储一个掩码,而是使用这些对象来表示呢?恰恰是因为节省了内存,因为这种对象
//的size是1个字节,所以我们需要对象时,仅仅是1个字节,而我们并不一定使用这个对象。为什么呢?首先我们明确这些类
//干什么用的,为了说明迭代器的类型。迭代器的类型信息经常会被使用吗?不经常,甚至可以说只是偶尔使用,那么我们如果使用
//掩码来表示类型,那么每个迭代器我们都需要至少2byte的数据来存储掩码,而我们需要为每个迭代器一个不常使用的特性浪费
//内存,这是不值得的。那么,使用下面的方法,效果如何呢?哈哈,对于iterator模板推断,其中使用typedef,size只有1byte,什么
//时候我们需要使用这个信息的时候,可是使用:动态识别。这个技术,在stl中没有涉及(mfc中有此技术);stl中使用了更巧妙的
//的方法,使用函数重载机制,利用此类型信息,具体的可参见使用与迭代器型别有关的算法
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};

下面是iterator的基本定义:

template <class _Category, class _Tp, class _Distance = ptrdiff_t,
          class _Pointer = _Tp*, class _Reference = _Tp&>
struct iterator {
  typedef _Category  iterator_category;
  typedef _Tp        value_type;
  typedef _Distance  difference_type;
  typedef _Pointer   pointer;
  typedef _Reference reference;
};

技术二:特性的提取:

//我们对于迭代器的使用,需要迭代器的特性,这个技术非常重要。
//试想,我们得知到一个迭代器类型,我们如何知道这个迭代器所指向的数据类型?这个问题非常常见,必须解决。这里就需要
//特性提取技术,这种技术基于一种协议:所有的迭代器中都有一种value_type,代表所指的数据类型,此问题提供了这一类解决
//问题的方法,定义一种协议,大家都遵循,我们就可以解决很多看似很难的问题。mfc中的大部分技术都是采用这一解决方案
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;
};
//指针作为一种特殊的迭代器,我们需要特化,特化如下,值得注意,注意细节的处理:const 指针和一般指针两个特化版本
template <class _Tp>
struct iterator_traits<_Tp*> {
  typedef random_access_iterator_tag iterator_category;
  typedef _Tp                         value_type;
  typedef ptrdiff_t                   difference_type;
  typedef _Tp*                        pointer;
  typedef _Tp&                        reference;
};

template <class _Tp>
struct iterator_traits<const _Tp*> {
  typedef random_access_iterator_tag iterator_category;
  typedef _Tp                         value_type;
  typedef ptrdiff_t                   difference_type;
  typedef const _Tp*                  pointer;
  typedef const _Tp&                  reference;
};

//下面的技术用来提取迭代器的特性,为甚么这么做呢,直接使用_Iter::value_type不行吗?试想,如果迭代器是指针怎么办?
//很明显,我们需要迭代器对于指针的特化版本,
//首先想一下基于迭代器的算法的格式:template<class InputIter> function(InputIter __x)
//当我们__x是一个指针时,我们的InputIter被推断为指针,如何从指针中得出类型信息呢?指针并不是迭代器而是迭代器的一种特殊形式,
//两者的基本实现是不同的,但是都可以看做是迭代器,什么意思呢?就是说迭代器与指针是不同的两种东西,但是其性质是相似的
//我们需要一个包装,能涵盖这两个东西,而不是将指针实现为迭代器的特殊版本---这是不可能的。而这个包装就是大名鼎鼎的
//iterator_traits!

关于特性提取,类似的技术还有type_traits:

//这里采用与iterator一样的技术,标志用类来表示
struct __true_type {
};

struct __false_type {
};

template <class _Tp>
struct __type_traits { 
   typedef __true_type     this_dummy_member_must_be_first;

   typedef __false_type    has_trivial_default_constructor;
   typedef __false_type    has_trivial_copy_constructor;
   typedef __false_type    has_trivial_assignment_operator;
   typedef __false_type    has_trivial_destructor;
   typedef __false_type    is_POD_type;
};

说明一点:对于任意的类型,借助于type_traits,我们都有type_traits(即使是未定义)。所以最基本的type_traits是保证最低需求的:假设构造,复制等等都需要显示的操作。而对于确实不需要显示的复制,构造的类型,我们可以使用模板特化,例如:

template<> struct __type_traits<char*> {
   typedef __true_type    has_trivial_default_constructor;
   typedef __true_type    has_trivial_copy_constructor;
   typedef __true_type    has_trivial_assignment_operator;
   typedef __true_type    has_trivial_destructor;
   typedef __true_type    is_POD_type;
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值