STL源碼分析--iterator

更多精彩內容,請關注微信公衆號:後端技術小屋後端

1 相關頭文件

iterator
iterator.h 
stl_iterator.h
stl_iterator_base.h

2 輸入迭代器

2.1 iterator的種類

在STL中,迭代器分爲輸入迭代器、輸出迭代器、前向迭代器、雙向迭代器、隨機訪問迭代器。這裏先講輸入迭代器這個大類。數組

  • 輸入迭代器: input_iterator
    輸入迭代器指向的位置只能被順序讀取(iterator_category類型爲input_iterator_tag)。在每種迭代器類型中,必須定義iterator_category表示迭代器種類,value_type表示迭代器指向的實例類型,difference_type表示迭代器距離的類型,pointer表示迭代器指向的實例的指針類型,reference表示實例應用類型。
template <class _Tp, class _Distance> struct input_iterator {
  typedef input_iterator_tag iterator_category;
  typedef _Tp                value_type;
  typedef _Distance          difference_type;
  typedef _Tp*               pointer;
  typedef _Tp&               reference;
};
  • 輸出迭代器:ouput_iterator
    輸出迭代器指向的位置只能被順序寫入(iterator_category類型爲output_iterator_tag)
struct output_iterator {
  typedef output_iterator_tag iterator_category;
  typedef void                value_type;
  typedef void                difference_type;
  typedef void                pointer;
  typedef void                reference;
};
  • 前向迭代器: forward_iterator
    前向迭代器只能自增不能自減,它是一種特殊的輸入迭代器(iterator_category類型爲forward_iterator_tag,然後者正是input_iterator_tag的派生類)
template <class _Tp, class _Distance> struct forward_iterator {
  typedef forward_iterator_tag iterator_category;
  typedef _Tp                  value_type;
  typedef _Distance            difference_type;
  typedef _Tp*                 pointer;
  typedef _Tp&                 reference;
};


struct forward_iterator_tag : public input_iterator_tag {};
  • 雙向迭代器:bidirectional_iterator
    雙向迭代器既能自增,又能自減,它是一種特殊的前向迭代器(可以自減的前向迭代器)。注意iterator_category類型爲bidirectional_iterator_tag,然後者正是forward_iterator_tag的派生類。
template <class _Tp, class _Distance> struct bidirectional_iterator {
  typedef bidirectional_iterator_tag iterator_category;
  typedef _Tp                        value_type;
  typedef _Distance                  difference_type;
  typedef _Tp*                       pointer;
  typedef _Tp&                       reference;
};


struct bidirectional_iterator_tag : public forward_iterator_tag {};
  • 隨機訪問迭代器:random_access_iterator
    隨機訪問迭代器,是一種特殊的雙向迭代器,除了自增自減1以外,還能自增自減n。注意iterator_category類型爲random_access_iterator_tag,然後者正是bidirectional_iterator_tag的派生類。
template <class _Tp, class _Distance> struct random_access_iterator {
  typedef random_access_iterator_tag iterator_category;
  typedef _Tp                        value_type;
  typedef _Distance                  difference_type;
  typedef _Tp*                       pointer;
  typedef _Tp&                       reference;
};

2.2 iterator類型萃取

做用:將不一樣種類迭代器中定義的iterator_category, value_type, difference_type, pointer, reference類型轉化爲萃取器自身的類型。當上層調用萃取器iterator_traits時,迭代器類型(做爲iterator_traits的模板參數)對上層是透明的。微信

實現以下,因爲2.1中全部迭代器中,都定義了iterator_category等類型,iterator_traits即可將迭代器中的類型導出做爲自身類型。dom

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;
};

某些特殊狀況下,原始指針_Tp*也可做爲iterator使用(例如數組中的原始指針)。由於_Tp*內部並未定義以上類型,所以iterator_traits須要對_Tp*const _Tp*進行特化。函數

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;
};

有了iterator_traits,迭代器操做即可根據不一樣的類型進行不一樣的實現。源碼分析

2.3 iterator_category函數(返回迭代器種類)

實現以下,模板入參爲迭代器,iterator_category函數所返回的是迭代器中iterator_category類型的實例。this

template <class _Iter>
inline typename iterator_traits<_Iter>::iterator_category
iterator_category(const _Iter& __i) { return __iterator_category(__i); }


template <class _Iter>
inline typename iterator_traits<_Iter>::iterator_category
__iterator_category(const _Iter&)
{
  typedef typename iterator_traits<_Iter>::iterator_category _Category;
  return _Category();
}

2.4 distance函數(返回兩迭代器之間距離)

實現以下,首先經過iterator_category函數獲取迭代器種類,再將其值做爲參數傳給__distance函數。指針

template <class _InputIterator, class _Distance>
inline void distance(_InputIterator __first, 
                     _InputIterator __last, _Distance& __n)
{
  __STL_REQUIRES(_InputIterator, _InputIterator);
  __distance(__first, __last, __n, iterator_category(__first));
}

返回結果關鍵在於__distance函數。對於不一樣的迭代器類型,重載了不一樣的__distance實現,這些實現使用了迭代器中的iterator_category類型進行區分。code

例如:對於隨機訪問迭代器類型,計算distance只需將兩個迭代器相減便可。對象

template <class _RandomAccessIterator, class _Distance>
inline void __distance(_RandomAccessIterator __first, 
                       _RandomAccessIterator __last, 
                       _Distance& __n, random_access_iterator_tag)
{
  __STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator);
  __n += __last - __first;
}

對於其餘迭代器(都屬於input_iterator類型),實現上則須要從__first步步遞進並計數,直到到達__last爲止,最後返回計數值

template <class _InputIterator, class _Distance>
inline void __distance(_InputIterator __first, _InputIterator __last,
                       _Distance& __n, input_iterator_tag)
{
  while (__first != __last) { ++__first; ++__n; }
}

2.5 advance函數(迭代器偏移n個位置)

對於advance函數, 不一樣類型迭代器其實現也不盡相同。

  • random_access_iterator:隨機訪問迭代器支持一次跳轉多步,所以可一次跳轉至目標位置
  • bidirectional_iterator: 雙向迭代器同時支持前向自增1和後向自增1。若是n>=0, 迭代器重複執行n次自增1, 若是n<0, 迭代器重複執行-n次自減1
  • input_iterator: 輸入迭代器只能支持前向自增1。n必須大於等於零,此時迭代器執行n次自增1。
template <class _InputIterator, class _Distance>
inline void advance(_InputIterator& __i, _Distance __n) {
  __STL_REQUIRES(_InputIterator, _InputIterator);
  __advance(__i, __n, iterator_category(__i));
}


template <class _RandomAccessIterator, class _Distance>
inline void __advance(_RandomAccessIterator& __i, _Distance __n, 
                      random_access_iterator_tag) {
  __STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator);
  __i += __n;
}


template <class _BidirectionalIterator, class _Distance>
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 _InputIter, class _Distance>
inline void __advance(_InputIter& __i, _Distance __n, input_iterator_tag) {
  while (__n--) ++__i;
}

2.6 反向迭代器

反向迭代器通常用於逆向遍歷容器。其自增和自減的方向與其封裝的迭代器正好是反過來的。

iterator_type base() const { return current; }
  reference operator*() const {
    _Iterator __tmp = current;
    return *--__tmp;
  }


  _Self& operator++() {
    --current;
    return *this;
  }
  _Self operator++(int) {
    _Self __tmp = *this;
    --current;
    return __tmp;
  }
  _Self& operator--() {
    ++current;
    return *this;
  }
  _Self operator--(int) {
    _Self __tmp = *this;
    ++current;
    return __tmp;
  }

構造時,輸入類型爲_Iterator的迭代器對象__x, reverse_iterator<_Iterator>即爲_Iterator的逆操做。API以下:

  • base: 返回被封裝的__x迭代器
  • operator*: 返回*(__x-1) (容器的end iterator爲虛邊界,當基於end iterator生成反向迭代器時,執行operator*應當返回容器的最後一個元素)
  • operator++: __x自減1
  • operator--: __x自增1

3 輸出迭代器

back_inserter_iterator, front_insert_iterator, insert_iterator中都定義了iterator_category類型爲output_iterator_tag。所以它們都是輸出迭代器。

back_insert_iterator爲例,其中模板參數_Container爲STL容器類型,iterator_categoryoutput_iterator_tag類型。

template <class _Container>
class back_insert_iterator {
protected:
  _Container* container;
public:
  typedef _Container          container_type;
  typedef output_iterator_tag iterator_category;
  ...
};

3.1 back_insert_iterator

用於向容器尾部插入元素

back_insert_iterator<_Container>&
  operator=(const typename _Container::value_type& __value) { 
    container->push_back(__value);
    return *this;
  }

back_inserter_iterator執行operator=操做時,老是對容器push_back(容器必須實現push_back接口)

3.2 front_insert_iterator

用於向容器頭部插入元素

explicit front_insert_iterator(_Container& __x) : container(&__x) {}
  front_insert_iterator<_Container>&
  operator=(const typename _Container::value_type& __value) { 
    container->push_front(__value);
    return *this;

front_inserter_iterator執行operator=操做時,老是對容器push_front(容器必須實現push_front接口)

3.3 insert_iterator

用於向容器指定位置插入元素

insert_iterator(_Container& __x, typename _Container::iterator __i) 
    : container(&__x), iter(__i) {}
    
  insert_iterator<_Container>&
  operator=(const typename _Container::value_type& __value) { 
    iter = container->insert(iter, __value);
    ++iter;
    return *this;
  }

insert_iterator構造時傳入容器和迭代器iter,執行operator=操做時,老是對容器執行insert, 插入位置由迭代器iter決定(容器必須實現insert接口)

推薦閱讀

更多精彩內容,請掃碼關注微信公衆號:後端技術小屋。若是以爲文章對你有幫助的話,請多多分享、轉發、在看。
二維碼

相關文章
相關標籤/搜索