容器结构分类
这里的衍生,并非继承关系,而是一种包含关系。
例如heap中包含一个vector。
通过萃取机traits萃取迭代器的型别
template <class I>
struct iterator_traits { //traits是特性之意
typedef typename I::value_type value_type;
};
//两个偏特化(partial specialization)
template <class T>
struct iterator_traits<T*> {
typedef T value_type;
};
template <class T>
struct iterator_traits<const T*> {
typedef T value_type; //注意是T而不是const T,因为value_type的主要目的是用来声明变量,而声明一个无法被赋值的变量是没有什么用的(const T),所以要去掉const
};
//于是当需要知道I的value_type时,便可以这么写:
template<typename I>
void algorithm(...) {
typename iterator_traits<I>::value_type v1;
}
容器list
list在要内存时,不光需要一个指针,还需要指向前后的两个指针。
list的定义
//list的定义
template<class T, class Alloc = alloc>
class list {
protected:
typedef __list_node<T> list_node;
public:
typedef list_node* link_type;
//G2.9编译器的iterator
typedef __list_iterator<T, T&, T*> iterator;
//G4.9编译器的iterator
typedef _List_iterator<_Tp> iterator;
portected:
link_type node;
};
list的node定义
G2.9编译器的设计是如下所示:其中前向指针和后向指针,指向的都是void类型,所以sizeof(list)是4个字节,就是一个指向数据的指针。
//list节点的定义
template <class T>
struct __list_node {
typedef void* void_pointer;
void_pointer prev;
void_pointer next;
T data;
};
G4.9版本在G2.9版本的基础之上,将node部分拆分成了两个部分,一个是_list_node_base
,改变了G2.9版本的前向和后向指针的指向类型,另外node是继承_List_node_base
后,再加上数据部分,如下所示:
//G4.9编译器,list节点的定义:
struct _List_node_base {
_List_node_base* _M_next;
_List_node_base* _M_prev;
};
template<typename _Tp>
struct _List_node : public _List_node_base {
_Tp _M_data;
};
list的iterator
list的存储是非连续空间,所以list的iterator不能是普通指针。而是定义一个class来模拟指针,称之为smart pointer
如上图红色的泡泡,当list的iterator加一时,应该指向下一个节点的位置。所以list的iterator是一个smart pointer.
每个iterator要有5个typedef,因为迭代器是容器和算法之间的桥梁,所以迭代器必须定义这五种typedef,以便于回答算法的提问:
传入类型T的参数,直接T::iterator_category,就可以得到迭代器的类型。
- iterator_category
- value_type
- difference_type
- pointer
- reference
list的五个reference如下所示:
//list的五个typedef定义
template<typename _TP>
struct _List_iterator {
typedef std::bidirectional_iterator_tag iterator_category;
typedef _Tp value_type;
typedef _Tp* pointer;
typedef _Tp& reference;
typedef ptrdiff_t difference_type;
};
还有一大堆的操作符重载。
//list的iterator的定义
template <typename _Tp>
struct _List_iterator {
typedef _Tp* poinetr;
typedef _Tp& reference;
};
容器vector
vector的扩充方式是两倍增长,换一个内存后进行两倍增长。
vector的定义
//vector的定义
template <class T,class Alloc = alloc>
class vector{
public:
typedef T value_type;
typedef value_type* iterator;//T*
typedef value_type& reference;
typedef size_t size_type;
protected:
iterator start;
iterator finish;
iterator end_of_storage;
public:
iterator begin() { return start; }
iterator end() { return finish; }
size_type size() const { //大小 finish-start
return size_type(end() - begin());
}
size_type capacity() const { //容量
return size_type(end_of_storage - begin());
}
bool empty() const { return begin() == end(); }
reference operator[](size_type n) { //连续空间的中括号
return *(begin() + n);
}
reference front() { return *begin(); } //取出首个元素
reference back() { //取出尾部元素
return *(end() - 1);
}
}
vector的iterator
//vector的迭代器设计
template <class T, class Alloc = alloc>
class vector {
public:
typedef T value_type;
typedef value_type* iterator; //T*
};
vector<int>vec;
vector<int>::iterator ite = vec.begin();
vector 的大小
vector的大小是三个指针,start,finish,end_of_storage,这三个指针的大小是12.
array
array的定义
//array的定义
template <typename _Tp, std::size_t _Nm>
struct array{
typedef _Tp value_type;
typedef _Tp* pointer;
typedef value_type* iterator;
//支持0大小的数组生成
value_type _M_instance[_Nm ? _Nm : 1];
iterator begin() {
return iterator(&_M_instance[0]);
}
iterator end() { //最后一个元素的下一个元素
return iterator(&_M_instance[_Nm]);
}
};
forward_list
forward_list与list的区别
单向链表与list的区别仅仅只在于一个是单向,一个是双向,其他都是相同的。
deque
deque是一个双向开口的连续线性空间,其实是动态的以分段连续空间组合而成 ,外界以为它是连续的。
deque是由一段一段定量的连续空间构成,一旦有必要在deque的前端或后端增加新空间时,便配置一段定量的连续空间,串接在整个deque的头端或尾端,deque的最大任务就是在这些分段的定量连续空间上,维护其整体连续的假象,并提供随机存取的接口,避开了“重新配置、复制、释放”的轮回,代价则是复杂的迭代器架构。
如上图所示,deque管理一个map(一小块连续空间),map是一个vector,其中每个元素是一个指针,指向另一段较大的连续线性空间,称为缓冲区。
deque的定义
//一个deque的大小是40个字节
template <class T,class Alloc = alloc, size_t BufSiz = 0> //BufSizs是buffer的大小
class deque {
public:
typedef T value_type;
typedef __deque_iterator<T, T&, T*, BufSiz>iterator;
protected:
typedef pointer* map_pointer; //T**
protected:
iterator start; //大小是16个字节
iterator finish; //大小是16个字节
map_pointer map; //控制中心是个vector,是会2倍动态增长的 T** 指向指针的指针 大小是4
size_type map_size; //大小是4字节
public:
iterator begin() { return start; }
iterator end() { return finish; }
iterator size() const { return finish - start; }
};
deque的iterator
deque的迭代器包含四个部分:cur first last node
//deque的iterator
template <class T, class Ref, class Ptr,size_t BufSiz>
struct __deque_iterator {
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef Ptr pointer;
typedef Ref reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T** map_pointer;
typedef __deque_iterator self;
T* cur;
T* first;
T* last;
map_pointer node;
};