STL源码剖析:迭代器

迭代器是什么

迭代器是一种模式,实现了通过一个统一接口访问STL容器的方法。STL作为桥梁链接了STL算法与容器。例如,我们可以通过Sort(a.begin() , a.end())完成一次利用算法对vector类型容器a的排序。

迭代器的设计

标准STL中,迭代器在容器内部,每种容器都有自己专属的迭代器。这样做的原因是,如果要创建迭代器,就必须访问容器的内部结构,所以直接封装进容器内部是最简单的方式。

如何获得迭代器指向的数据类型

迭代器的设计过程中需要获得迭代器指向的数据类型,有效的一种方式是通过Traits来提取Value Type,对于原生指针,可以提取出指针指向的Value Type。如:

template<calss T>
struct Test<T*>{
	typedef T value_type;
}

通过实现多个不同的Template 特化版本,就能实现多种数据类型的类型提取

迭代器的五种类型

  1. input iterator 只读
  2. output iterator 只写
  3. forward iterator 允许区间操作
  4. bidlrectional iterator 双向移动
  5. random access iterator 支持随机访问
    内部继承关系

迭代器内部常用的五种型别

  1. value type : 内部值的类型
  2. difference type : 表示迭代器之间的距离
  3. reference type : 内部数据的引用类型。代表着iter指向的内容是否是const的,如果不是const那么解引用应该返回引用(左值)而不是值(右值)
  4. pointer type : 内部数据的指针类型
  5. iterator_category : iterator的类型。需要根据不同类型做出不同响应

std::iterator

STL提供了一个iterator基类,自己实现的iterator只要继承此类就能够保证实现了五个型别

    template<class T>
    struct iterator_traits<T*>
    {
        typedef random_access_iterator_tag  iterator_category; // 指针的category是random类型
        typedef T                           value_type;
        typedef ptrdiff_t                   difference_type;
        typedef T*                          pointer;
        typedef T&                          reference;
    };

    //针对Pointer-to-const而设计的traits偏特化版本
    template<class T>
    struct iterator_traits<const T*>
    {
        typedef random_access_iterator_tag  iterator_category;
        typedef T                           value_type;
        typedef ptrdiff_t                   difference_type;
        typedef const T*                    pointer;
        typedef const T                     reference;
    };

流程总结

    //五种迭代器,作为tag供重载使用
    struct input_iterator_tag{};
    struct output_iteratoe_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 _InputIter, class _Distance>  
/*迭代器类型为input_iterator_tag的函数定义*/  
inline void __advance(_InputIter& __i, _Distance __n, input_iterator_tag) {  
  while (__n--) ++__i;  
}  

template <class _BidirectionalIterator, class _Distance>  
/*迭代器类型为bidirectional_iterator_tag的函数定义*/  
inline void __advance(_BidirectionalIterator& __i, _Distance __n,   
                      bidirectional_iterator_tag) {  
  __STL_REQUIRES(_BidirectionalIterator, _BidirectionalIterator);  
  if (__n >= 0)  
    while (__n--) ++__i;  
  else  
    while (__n++) --__i;  
}  

template <class _RandomAccessIterator, class _Distance>  
/*迭代器类型为random_access_iterator_tag的函数定义*/  
inline void __advance(_RandomAccessIterator& __i, _Distance __n,   
                      random_access_iterator_tag) {  
  __STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator);  
  __i += __n;  
}  

template <class _InputIterator, class _Distance>  
/*决定调用哪个函数,这是一个对外接口*/  
inline void advance(_InputIterator& __i, _Distance __n) {  
  __STL_REQUIRES(_InputIterator, _InputIterator);  
  __advance(__i, __n, iterator_category(__i));  
} 

SGI对traits进行扩展

iterator_traits负责萃取迭代器的特性,__type_traits负责萃取型别(type)的特性

  1. 是否具备non-trivial default ctor?
  2. 是否具备non-trivial copy ctor?
  3. 是否具备non-trivial assignment operator?
  4. 是否具备non-trivial dtor?
  5. 是否为POD(plain old data)型别?

通过指定类型,在编译期间决定以上特性 ,来避免额外调用(如construct , destruct等),提高效率

	 struct _true_type{};
	 struct _false_type{};

    /*
     *非基本数据类型,默认指定为_false_type只能自己初始化,不能系统进行
     */
    template<class T>
    struct _type_traits
    {
        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   has_POD_type;
    };
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章