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;
    };
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章