STL迭代器(一)

迭代器學習(一)

《STL 源碼剖析》中,第三章叫“迭代器概念與traits編程技法”。總共33頁,我艱難的讀了一遍,愚蠢的我還是被所謂“traits技法”驚呆了!說白了,想要真正明白迭代器,就必須瞭解traits編程技術。
但不忙,在看什麼是traits之前,先看看什麼叫“迭代器”:迭代器是一種設計模式,他要求提供一種方法,使之能夠一次訪問某個聚合物內部的元素,而又無需暴露該聚合物內部的表達方式。也就是說,迭代器就是一個不需要知道聚合物內部實現細節而又可以訪問聚合物內部元素的東西!
那迭代器有什麼用呢?特別是在STL裏面,迭代器扮演着什麼樣的角色呢?
在STL裏面,容器與算法是分開設計的,容器是容器,算法是算法,那我們要是想在容器裏面用算法可怎麼辦呢?難不成還需要實現一個特殊版本的內部算法?那豈不是會造成大量的代碼冗餘,無論誰看都不雅啊!
那,解決一個問題,就需要了解問題的本質,那上面這個問題的本質是什麼呢?也就是說,我們用在容器裏面使用算法,需要什麼?我相信誰都知道,一個算法只有用在數據之上纔有價值,也就是說,只要我們能夠操作容器的數據,就可以使用算法來做一些事情,這時候,迭代器就排上用場了,再想想迭代器的概念,是不是有種首尾呼應的感覺呢?
好了,明白了這個簡單的道理,就要去啃一個難點,就是traits編程技術,那我們需要了解什麼叫traits編程技術,需要說明的一點是,我覺得某位老師說的一句話非常對:“概念是最大的認知障礙”,也就是,當我們在沒有明白什麼叫什麼的前提下去學習什麼,那麼會非常困難,如果在做事情之前瞭解什麼叫什麼,那事情就會變得容易得多。
所以,首先,什麼叫traits編程技術呢?在看了書,查資料之後,我覺得下面的定義較爲妥當:traits編程技術就是通過模板的類型推導機制,獲得變量的類型,而後決定dispatch到哪個函數。
爲什麼需要traits技術呢?因爲c++是弱類型的,所以沒有所謂typeof,只要sizeof,但sizeof之後又不能確定類型,因爲sizeof(bool)==sizeof(char)你有什麼辦法,當然如果硬要實現的話,可能真的可以也說不定,就是麻煩點,但是依靠c++中的模板類型推導機制,可以快速方便的獲得類型,這不是更好嘛?
在討論更加深入的內容之前,還需要在講一個東西,那就是指針,根據迭代器的概念,指針也可以算是一種迭代器,但很明顯指針不是類,那就沒有辦法依靠模板類型推導來得到變量的具體類型了,那怎麼辦呢?沒事,加上一個特化版本就可以了。
又來了,什麼叫特化版本呢?其實原來叫”partial specialization”,意思是提供另一分template定義,而其本身仍爲templatized。
好了,再次整理traits技術,更加通俗易懂一點,traits就是一個“特性萃取器”,來什麼,就可以提取出是什麼類型,好厲害!
在標準STL裏面,有5種最常用的迭代器,下面對這些迭代器做一些簡要介紹:
(1)、value_type ,即迭代器所指對象的型別
(2)、difference_type ,用來表示兩個迭代器之間的距離,他可以用來表示一個容器的最大容量但要求是這個迭代器具有連續空間
(3)、reference_type,引用
(4)、pointer_type,指針
(5)、iterator_category,迭代器類別
上面第五個提到的迭代器類型,說是迭代器類別?這是什麼鬼?不急,我們先來看看迭代器的類別再說話:
(1)、Input_iterator,這種迭代器所指向的對象,不允許外界改變,只讀
(2)、Output_iterator,只寫
(3)、Forward_iterator,讀寫操作都可以,單向
(4)、Bidirectional_iterator,可雙向移動
(5)、Random_access_iterator,隨機的啊

現在我們應該明白了吧,iterator_category就是上面五種迭代器類型之中的一個。

好了,有了上面介紹的這些知識,可以懷着忐忑的心情去看STL的源代碼了。下面是對文件

//下面是五種迭代器類型,僅僅是作爲標記用,沒有任何成員,所以不會有任何負擔
//其中使用了繼承
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;
};

//要是想開發自己的迭代器,最好繼承下面這個類吧,因爲沒有什麼東西,所以不會造成什麼壓力
#ifdef __STL_USE_NAMESPACES
template <class Category, class T, class Distance = ptrdiff_t,
          class Pointer = T*, class Reference = T&>
struct iterator {
  typedef Category  iterator_category;
  typedef T         value_type;
  typedef Distance  difference_type;
  typedef Pointer   pointer;
  typedef Reference reference;
};
#endif /* __STL_USE_NAMESPACES */

#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION

//下面就開始展示traits編程技術了
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;
};

//針對原聲指針做的特化版本
template <class T>
struct iterator_traits<T*> {
  typedef random_access_iterator_tag iterator_category;
  typedef T                          value_type;
  typedef ptrdiff_t                  difference_type;
  typedef T*                         pointer;
  typedef T&                         reference;
};

//針對原聲常量指針做的偏特化版本
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;
};

//這個函數將很容易的決定某個迭代器的類型
template <class Iterator>
inline typename iterator_traits<Iterator>::iterator_category //返回類型
iterator_category(const Iterator&) {
  typedef typename iterator_traits<Iterator>::iterator_category category;
  return category();
}

//返回迭代器的difference_type
template <class Iterator>
inline typename iterator_traits<Iterator>::difference_type*
distance_type(const Iterator&) {
  return static_cast<typename iterator_traits<Iterator>::difference_type*>(0);
}

//返回迭代器的value_type,也就是迭代器所指向的對象的類型
template <class Iterator>
inline typename iterator_traits<Iterator>::value_type*
value_type(const Iterator&) {
  return static_cast<typename iterator_traits<Iterator>::value_type*>(0);
}

#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */

template <class T, class Distance> 
inline input_iterator_tag 
iterator_category(const input_iterator<T, Distance>&) {
  return input_iterator_tag();
}

inline output_iterator_tag iterator_category(const output_iterator&) {
  return output_iterator_tag();
}

template <class T, class Distance> 
inline forward_iterator_tag
iterator_category(const forward_iterator<T, Distance>&) {
  return forward_iterator_tag();
}

template <class T, class Distance> 
inline bidirectional_iterator_tag
iterator_category(const bidirectional_iterator<T, Distance>&) {
  return bidirectional_iterator_tag();
}

template <class T, class Distance> 
inline random_access_iterator_tag
iterator_category(const random_access_iterator<T, Distance>&) {
  return random_access_iterator_tag();
}

template <class T>
inline random_access_iterator_tag iterator_category(const T*) {
  return random_access_iterator_tag();
}

template <class T, class Distance> 
inline T* value_type(const input_iterator<T, Distance>&) {
  return (T*)(0); 
}

template <class T, class Distance> 
inline T* value_type(const forward_iterator<T, Distance>&) {
  return (T*)(0);
}

template <class T, class Distance> 
inline T* value_type(const bidirectional_iterator<T, Distance>&) {
  return (T*)(0);
}

template <class T, class Distance> 
inline T* value_type(const random_access_iterator<T, Distance>&) {
  return (T*)(0);
}

template <class T>
inline T* value_type(const T*) { return (T*)(0); }

template <class T, class Distance> 
inline Distance* distance_type(const input_iterator<T, Distance>&) {
  return (Distance*)(0);
}

template <class T, class Distance> 
inline Distance* distance_type(const forward_iterator<T, Distance>&) {
  return (Distance*)(0);
}

template <class T, class Distance> 
inline Distance* 
distance_type(const bidirectional_iterator<T, Distance>&) {
  return (Distance*)(0);
}

template <class T, class Distance> 
inline Distance* 
distance_type(const random_access_iterator<T, Distance>&) {
  return (Distance*)(0);
}

template <class T>
inline ptrdiff_t* distance_type(const T*) { return (ptrdiff_t*)(0); }

#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */

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

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

#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION

template <class InputIterator>
inline iterator_traits<InputIterator>::difference_type
__distance(InputIterator first, InputIterator last, input_iterator_tag) {
  iterator_traits<InputIterator>::difference_type n = 0;
  while (first != last) {
    ++first; ++n;
  }
  return n;
}

template <class RandomAccessIterator>
inline iterator_traits<RandomAccessIterator>::difference_type
__distance(RandomAccessIterator first, RandomAccessIterator last,
           random_access_iterator_tag) {
  return last - first;
}

template <class InputIterator>
inline iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last) {
  typedef typename iterator_traits<InputIterator>::iterator_category category;
  return __distance(first, last, category());
}

#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */

template <class InputIterator, class Distance>
inline void __advance(InputIterator& i, Distance n, input_iterator_tag) {
  while (n--) ++i;
}

#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma set woff 1183
#endif

template <class BidirectionalIterator, class Distance>
inline void __advance(BidirectionalIterator& i, Distance n, 
                      bidirectional_iterator_tag) {
  if (n >= 0)
    while (n--) ++i;
  else
    while (n++) --i;
}

#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma reset woff 1183
#endif

template <class RandomAccessIterator, class Distance>
inline void __advance(RandomAccessIterator& i, Distance n, 
                      random_access_iterator_tag) {
  i += n;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章