STL源碼分析之迭代器

前言

迭代器是將算法和容器兩個獨立的泛型進行調和的一個接口. 使咱們不須要關係中間的轉化是怎麼樣的就都能直接使用迭代器進行數據訪問. 而迭代器最重要的就是對operator *operator->進行重載, 使它表現的像一個指針.算法

類型

迭代器根據移動特性和實施操做被分爲5類dom

  1. input iterator(輸入迭代器) : 迭代器所指的內容不能被修改, 只讀且只能執行一次讀操做.
  2. output iterator(輸出迭代器) : 只寫而且一次只能執行一次寫操做.
  3. forward iterator(正向迭代器) : 支持讀寫操做且支持屢次讀寫操做.
  4. bidirectional iterator(雙向迭代器) : 支持雙向的移動且支持屢次讀寫操做.
  5. random access iterator(隨即訪問迭代器) : 支持雙向移動且支持屢次讀寫操做. p+n, p-n等.

1~4類迭代器執行操做的就如 : p++, ++p, p->而不是5類的p+n操做. 不明白的咱們下面會進行講解.函數

源碼分析

category的五類迭代器以及繼承關係源碼分析

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

這五個類都是空類, 只是爲了以後調用時經過類選擇不一樣的重載函數. 繼承是爲了可使用傳遞調用,當不存在某種迭代器類型匹配時編譯器會依據繼承層次向上查找進行傳遞, 就能夠經過繼承關係來決定選擇最優的調用. 咱們經過用distance來說最優.指針

distance是用於計算連個迭代器之間的距離, 由於重載就能夠經過不一樣的迭代器類型選擇不一樣的函數來提升效率.code

這裏distanceiterator_category函數是每一個迭代器本身定義的, 跟traits萃取器相關我準備放在下一篇章講解. 這裏只要知道它能經過first參數推斷出是哪一類的迭代器從而選擇調用哪個函數.繼承

template <class InputIterator, class Distance>
inline void distance(InputIterator first, InputIterator last, Distance& n) 
{
    __distance(first, last, n, iterator_category(first));
}
    
template <class InputIterator, class Distance>
inline void __distance(InputIterator first, InputIterator last, Distance& n, 
                       input_iterator_tag) 
{
    while (first != last) 
    { ++first; ++n; }
}

template <class RandomAccessIterator, class Distance>
inline void __distance(RandomAccessIterator first, RandomAccessIterator last, 
                       Distance& n, random_access_iterator_tag) 
{
    n += last - first;
}

distance源碼能夠看出來不一樣的迭代器的計算方式並不同, random_access_iterator_tag的距離的計算效率最高, 其餘都是經過++操做來依次訪問. 固然random_access_iterator_tag類的迭代器也是能夠調用input_iterator_tag, 可是顯然效率很低, 因此不一樣的迭代器最本身最佳的效率. 經過iterator_category進行最優選擇.接口

五類迭代器源碼

五類迭代器的結構體, 能夠看出來每一個類都定義了相同的變量名. 可是每一個名的類型不必定同樣, 提供統一的名是爲了traits進行類型萃取. 每一個類的iterator_category都是表明了不一樣的迭代器, 經過它來選擇該迭代器執行的函數.input

template <class T, class Distance> struct input_iterator 
{
    typedef input_iterator_tag iterator_category;
    typedef T                  value_type;
    typedef Distance           difference_type;
    typedef T*                 pointer;
    typedef T&                 reference;
};

struct output_iterator {
  typedef output_iterator_tag iterator_category;
  typedef void                value_type;
  typedef void                difference_type;
  typedef void                pointer;
  typedef void                reference;
};

template <class T, class Distance> struct forward_iterator {
  typedef forward_iterator_tag iterator_category;
  typedef T                    value_type;
  typedef Distance             difference_type;
  typedef T*                   pointer;
  typedef T&                   reference;
};


template <class T, class Distance> struct bidirectional_iterator {
  typedef bidirectional_iterator_tag iterator_category;
  typedef T                          value_type;
  typedef Distance                   difference_type;
  typedef T*                         pointer;
  typedef T&                         reference;
};

template <class T, class Distance> struct random_access_iterator {
  typedef random_access_iterator_tag iterator_category;
  typedef T                          value_type;
  typedef Distance                   difference_type;
  typedef T*                         pointer;
  typedef T&                         reference;
};

iterator_category判斷傳入迭代器的類型編譯器

template <class Iterator>
inline typename iterator_traits<Iterator>::iterator_category
iterator_category(const Iterator&) {
  typedef typename iterator_traits<Iterator>::iterator_category category;
  return category();
}

總結

這一篇僅僅只是講解了一些關於迭代器類型, 和一點traits的一點用法. 關於每一個迭代器都設置爲相同的類型名都是爲了traits萃取器作準備. 下篇進行探討.

相關文章
相關標籤/搜索