1. 程式人生 > >SGISTL原始碼閱讀五 迭代器上(迭代器的五種相應型別associated types)

SGISTL原始碼閱讀五 迭代器上(迭代器的五種相應型別associated types)

SGISTL原始碼閱讀五 迭代器上(迭代器的五種相應型別associated types)

前言

之前在對STL的簡介中說到過,迭代器的作用是將資料結構(容器)和演算法粘合在一起,我們可以將它理解成smart pointer,它是一種行為類似指標的物件。

什麼是相應型別?

最初看到這個翻譯覺得這個概念特別高大上,但是我們不要把它想得太複雜。
相應型別其實就是其字面意思,它可以指迭代器所指物件的型別,但是它又不止於此,常用的迭代器相應型別有五種,分別是

  • iterator_category
  • value_type
  • difference_type
  • pointer
  • reference

為什麼要會存在相應型別?

我們知道迭代器的作用是將不同的資料結構和演算法粘合在一起,如果僅僅只針對一種資料結構,那當然是很簡單的了,原生指標都可以做到。迭代器使用相應型別,針對不同的型別使用不同的方式(通過模板偏特化實現),這樣能大大提高地效率。

五種相應型別的詳細介紹

iterator_category

根據移動特性與施行操作,迭代器被分為了五類,iterator_category區分了這五類迭代器。

  • Input Iterator
    這種迭代器所指的物件不允許外界改變(Read Only)
  • Output Iterator
    與上一個迭代器類似,這個迭代器所指的物件,Write Only
  • Forward Iterator
    這種迭代器允許在其所形成的區間上進行讀寫操作,但是隻能向前(operator++)
  • Bidirectional Iterator
    同樣可以進行讀寫操作,並且可以雙向移動(operator++,operator–)
  • Random Access Iterator
    第五種型別涵蓋了之前所有指標的算術能力(相加,相減,通過下標訪問等)

他們的從屬關係為:

在這裡插入圖片描述

value_type

這就是迭代器所指物件的型別。(型別==型別,但是更通俗一些)

difference_type

difference_type用來表示兩個迭代器之間的距離,也可以用來表示一個容器的最大容量(因為對於連續空間的容器而言,頭尾之間的距離就是其最大容量)。

pointer

這裡的pointer型別其實就是指標。

reference_type

其實也很好理解,用我們最初在學習函式的時候的一個經典樣例來說,交換a、b的值,其實就是傳值和傳引用的區別,這裡的reference_type就是引用。按照是否能改變迭代器所指之物來分,迭代器可以分為兩種:
1.constant iterators,不允許改變所指物件內容;
例如帶有const修飾符的,就不能被改變
2.mutable iterators,允許改變所指物件內容。


深入原始碼

//從這裡我們可以看到不同型別迭代器之間 的繼承關係
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 {};

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

在進行了一些分析之後再看原始碼其實很好懂了,根據迭代器的五種型別建立了5個相應的結構體,他們都是統一地,擁有五種相應型別。

引數推導機制

大家應該比較熟悉sizeof()吧,我們可以呼叫它來獲取變數的長度,但是至於變數的型別呢?C++並未支援typeof(),但是可以使用 引數推導機制 ,一旦函式被呼叫,編譯器會自動進行template引數推導。

總結

以上簡要介紹了迭代器的五種相應型別和迭代器的型別
但是並非任何情況下任何一種相應型別都可以利用上述的template引數推導機制來取得的。
後面我們將介紹到traits程式設計技法。