C++ STL與泛型編程第二週

分配器allocators
在大多數版本的STL中,allocator的操作就是重載了C語言的malloc()和free();
容器list
list容器是一個雙向環狀鏈表,由於容器“前閉後開”的特性,容器的最後一個元素不是指向容器的第一個元素,而是
指向一個空白節點。
template<class T>
struct _list_node  //(1)
{
 typedef void* void point;
 typedef_pointer prev;
 typedef_pointer next;
};
template<class T, class Alloc = alloc>
class list       //(2)
{
protected:
 typedef _list_node<T> list_node;
public:
 typedef list_node* link_node;
 typedef _list_iterator<T, T&, T*> iterator;
protected:
 link_node node;
}
template<class T, class Ref, class Ptr>
struct _list_iterator    //(3)
{
 typedef T value_type;
 typedef Ptr pointer;
 typedef Ref reference;
 ...
};
從上面我們可以看到,list有這幾個成員:list_node類型的節點以及指向這種節點的指針,還有就是list容器的迭代器。

iterator需要遵循的原則
迭代器是算法和容器之間的橋樑,算法是操作,容器是數據,由於泛型編程,所以作爲中間橋樑的迭代器必須告訴算法它想知道的事情,算法對容器的操作才能得以進行下去;
原則有5:
1.iterator_category:它指的是迭代器在被算法操作時選擇的策略,往前還是往後,可不可以有一次跳過多個迭代器等等。這策略的選取由容器自身的特性決定;
2.difference_type:兩個迭代器之間的距離,算法需要知道容器有多大;
3.value_type:指的是容器中存放的數據類型;
4.pointer:未使用;
5.reference:未使用;
下面以list容器爲例
template<class T>  //list容器的iterator
struct _List_iterator
{
   typedef std::bidirectional_iterator_tag  iteraator_category;
   typedef _Tp value_type;
   typedef _Tp*  pointer;
   typedef _Tp&  reference;
   typedef ptrdiff_t  difference_type;
}
template<typename I>
inline void
algorithm(I first,I last)    //算法
{
    ...
    I::iterator_category;
    I::pointer;
    I::reference;
    I::difference_type;
    ...
}
當使用者在使用list這種容器的時候,傳給algorithm的typename就是list,然後通過I::iterator_category可以知道迭代器的操作策略,指針,距離以及元素類型,從而實現算法對容器的操作;
但是如果iterator並非class而只是native pointer,algorithm該如何得知呢?這裏就需要用到iterator_traits。
Iterator Traits用以分離class iterators和non-class iterators,它利用偏特化達到目標。
如果想要知道I的value_type可以向下面這樣。
如果I是class iterator,就進入(1);
如果I是pointer to T,就進入(2);
如果是pointer to const T,就進入(3);
template<typename I,...>
void algorithm(...)
{
   typename iterator_traits<I>::valude_type v1;
}
template <class T>
struct iterator_traits  //(1)
{
    typedef typename I::value_type valude_type; 
};
struct iterator_traits<T*>  //(2)
{
    typedef T valude_type; 
};
struct iterator_traits<const T*>  //(3)
{
    typedef T valude_type; 
};
完整的iterator_traits
template<class T>
struct iterator_traits
{
 typedef typename I::iterator_category iterator_category;
 typedef typename I::value_type        value_type;
 typedef typename I::difference_type   difference_type;
 typedef typename I::pointer   pointer;
 typedef typename I::reference  reference;
};
template<class T>
struct iterator_traits<T*>
{
 typedef random_access_iterator_tag iterator_category;
 typedef T        value_type;
 typedef ptrdiff   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   difference_type;
 typedef T*   pointer;
 typedef T&  reference;
};

容器vector的迭代器
按理說vector裏面存放的元素是連續的,所以vector的iterator不必設計得那麼複雜,它可以是一個指針;下面是vector class。
template<class T,class Alloc = alloc>
class vector{
public:
  typedef T value_type;
  typedef value_type* iterator; //T*
}
當iterator被丟給萃取機後,萃取機得知iterator是T*,因此看上面完整的iterator_traits可以知道,會選擇第二個traits。

容器array
template<typename _Tp,std::size_t _Nm>
struct array
{
   typedef _Tp  value_type;
   typedef _Tp*  pointer;
   typedef value_type* iterator;
   value_typedef _M_instance[_Nm?Nm;1]
   iterator begin()
  {return iterator(&_M_instance[0]);}
   iterator end()
   {return iterator(&_M_instance[_Nm]);}
    ...
}
同樣的,array的iterator會被送到萃取機,萃取機取出array的value_type,difference_type,iterator_category,pointer以及reference;













發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章