在大多數版本的STL中,allocator的操作就是重載了C語言的malloc()和free();
list容器是一個雙向環狀鏈表,由於容器“前閉後開”的特性,容器的最後一個元素不是指向容器的第一個元素,而是
指向一個空白節點。
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;
}
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:未使用;
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 Traits用以分離class iterators和non-class iterators,它利用偏特化達到目標。
如果I是class iterator,就進入(1);
如果I是pointer to T,就進入(2);
如果是pointer to const T,就進入(3);
void algorithm(...)
{
typename iterator_traits<I>::valude_type v1;
}
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;
};
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。
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;
{return iterator(&_M_instance[0]);}
{return iterator(&_M_instance[_Nm]);}
...
}
同樣的,array的iterator會被送到萃取機,萃取機取出array的value_type,difference_type,iterator_category,pointer以及reference;