迭代器是什麼
迭代器是一種模式,實現了通過一個統一接口訪問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 特化版本,就能實現多種數據類型的類型提取
迭代器的五種類型
- input iterator 只讀
- output iterator 只寫
- forward iterator 允許區間操作
- bidlrectional iterator 雙向移動
- random access iterator 支持隨機訪問
迭代器內部常用的五種型別
- value type : 內部值的類型
- difference type : 表示迭代器之間的距離
- reference type : 內部數據的引用類型。代表着iter指向的內容是否是const的,如果不是const那麼解引用應該返回引用(左值)而不是值(右值)
- pointer type : 內部數據的指針類型
- 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)的特性
- 是否具備non-trivial default ctor?
- 是否具備non-trivial copy ctor?
- 是否具備non-trivial assignment operator?
- 是否具備non-trivial dtor?
- 是否爲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;
};