Loading

序列式容器

容器结构分类

这里的衍生,并非继承关系,而是一种包含关系。
例如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;

};

posted @ 2020-02-01 13:43  三只猫-  阅读(290)  评论(0编辑  收藏  举报