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
程式設計技法。