C++ STL与泛型编程第二周

来源:互联网 发布:win7怎么关闭端口命令 编辑:程序博客网 时间:2024/06/03 06:50
分配器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;













原创粉丝点击