stl_vector.h源码剖析

vector简述<STL源码剖析>
  • vector是动态空间,随着元素的加入,它的内部机制会自行扩充扩建以容纳新元素。因此,vector的运用对于内存的合理利用与运用的灵活性有很大的帮助
  • vector的实现技术,关键在于其对大小的控制以及重新配置时的数据移动效率。一旦vector有空间满载,此时扩充空间时"配置新空间/数据移动/释还旧空间"的大成本,时间成本很高。
vector实现
template <class T, class Alloc = alloc>  // 默认alloc为迭代器
class vector {
public:
	// 以下標示 (1),(2),(3),(4),(5),代表 iterator_traits 5个型别
	typedef T value_type;				// (1) 数据类型
	typedef value_type* pointer; 			// (2) 指针
	typedef const value_type* const_pointer;
	typedef const value_type* const_iterator;
	typedef value_type& reference; 		// (3) 引用
	typedef const value_type& const_reference;
	typedef size_t size_type;
	typedef ptrdiff_t difference_type; 	// (4)
	
	//因为vector为线性空间,所以原生数据类型的指针可以满足需要
	typedef value_type* iterator;


	// 空间配置器
	typedef simple_alloc<value_type, Alloc> data_allocator;

	//vector采用线性空间,两个迭代器指向数据的头跟尾
	//end_of_storage 执行容器尾
	iterator start;
	iterator finish;
	iterator end_of_storage;
	//默认初始化
	vector() : start(0), finish(0), end_of_storage(0) {}
	iterator begin() { return start; }
	iterator end() { return finish; }
	
	//往position插入元素x及申请内存
	void insert_aux(iterator position, const T& x);
	template <class T, class Alloc>
	void vector<T, Alloc>::insert_aux(iterator position, const T& x) {
	if (finish != end_of_storage) {  // 还有备用空间
		//在备用空间上finish的位置处用原来容器中的最后一个元素构造一个元素
		construct(finish, *(finish - 1));
		// 调整水位。
		++finish;
		// 以下做啥用?
		T x_copy = x;
		copy_backward(position, finish - 2, finish - 1);
		//将x赋值
		*position = x_copy;
	}
	else {		// 已无备用空间
		const size_type old_size = size();	
		// 配置规则:如果原大小为0(初始值为0),则配置 1(个元素大小);
		// 如果原大小不为0,则配置原大小的两倍,
		// 前半段用来放元数据,后半段备用。
		const size_type len = old_size != 0 ? 2 * old_size : 1;
		iterator new_start = data_allocator::allocate(len); // 申请内存
		iterator new_finish = new_start;
		try{
			// 将原vector的内容拷贝到新的vector
			new_finish = uninitialized_copy(start, position, new_start);
			// 为新元素在设定初值
			construct(new_finish, x);
			++new_finish;
			// 将原vector的备用空间中的数据也拷贝过来
			new_finish = uninitialized_copy(position, finish, new_finish);
		} 
		catch (...) {
			// "commit or rollback" 要么全部成功要么回滚。
			destroy(new_start, new_finish);
			data_allocator::deallocate(new_start, len);
			throw;
		}

		// 析构所有的元素
		destroy(begin(), end());
		deallocate();

		// 调整容器的迭代器
		//指向新的开头
		//执行新的end()
		//设置水位
		start = new_start;
		finish = new_finish;
		end_of_storage = new_start + len;
	}
}
	void push_back(const T& x) {
		if (finish != end_of_storage) {     // 判断是否还有备用空间
			construct(finish, x);   		// place new。在备用空间中调用析构函数
			++finish;                       // 调整水位高度
		}
		else                                // 已无备用空间
			insert_aux(end(), x);
	}

	void pop_back() {
		--finish;
		destroy(finish);	// 释放最后一个元素,调用析构函数
	}
	// 将迭代器position指向的节点删除
	iterator erase(iterator position) {
		if (position + 1 != end()) // 如果 p 不是指向最后一个元素
			// 将position之后的元素一一前移
			copy(position + 1, finish, position);

		--finish;  // 调整水位
		destroy(finish);	// 将最后一个元素释放
		return position;	// positon中的内容已经被下一个position中的内容覆盖了(所以并不是网上说的,迭代器指向了下一个元素,地址并没有变只是内容变了)
	}
	//其实是编译器强行在earse之后将迭代器中的成员变量_Myproxy值置为空了,此时不可以直接操作++。
	//而返回的迭代器是重新构造的,是用Position重新构造的一个临时变量迭代器的_Myproxy有值的
	//所以遍历时earse,要用iter = earse(iter)的返回值。先判断返回值是否等于end再做++,不然会报返回野指针的错误
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值