STL源码剖析:vector学习笔记

1Array是静态空间,大小一旦确定就不能改变。

          Vector是动态空间,每增加一个元素可以自动扩充空间。

 

2Vector维护的是一个连续线性空间,支持随机存取。

          为了降低空间配置时的速度成本,vector实际配置的大小可能比客户端需求的量更大一些,以备将来可能的扩充。这便是容量(capacity)的观念。换句话说,一个vecotr的容量永远大于或等于其大小。一旦容量等于大小,便是满载,下次再有新增元素,整个vector就得另觅居所。

         新增加元素时,如果超过当时的容量,则容量会扩充至两倍。如果两倍容量仍不足,就扩充至足够大的容量。

容量的扩张必须经历“重新配置、元素移动、释放原空间”等过程。

 

(3)vector缺省使用alloc作为空间配置器,并据此另外定义一个data_allocator,为的是更方便以元素大小为配置单位。

         //simple_alloc 是SGT STL的空间配置器

         typedef simple_alloc<value_type,Alloc> data_allocator;

        于是,data_allocator::allocate(n) 表示配置n个元素空间。

 

(4)动态增加大小,并不是在原空间之后持续新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原大小的两倍另外配置一块较大空间,然后将原内容拷贝过来,之后才开始在原内容之后构造新元素,并释放原空间。

        因此对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了。


//alloc 是SGI STL的空间配置器
template<class T,class Alloc = alloc>
class vector{
	typedef T    value_type;
	typedef value_type* pointer;
	typedef value_type* iterator;   //vector的迭代器是普通指针
	typedef value_type& reference;
	typedef size_t           size_type;
	typedef ptrdiff_t        difference_type;

protected:
	//simple_alloc 是SGT STL的空间配置器
	typedef simple_alloc<value_type,Alloc> data_allocator;
	iterator start;
	iterator finish;
	iterator end_of_storage;  //表示目前可用空间的尾。指向整块连续空间(含备用空间)的尾端

	void insert_aux(iterator position,const T& x);
	void insert(iterator position,size_type n,const T& x);
	void deallocate(){
		if(start)
			data_allocator::deallocate(start,end_of_storage-start);
	}

	//填充并予以初始化
	void fill_initialize(size_type n,const T& value){
		start = allocate_and_fill(n,value);
		finish = start +n;
		end_of_storage = finish;
	}

public:
	iterator begin(){return start;}
	iterator end(){return finish;}
	size_type size() const {
		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);
	}

	//construct function
	vector():start(0),finish(0),end_of_storage(0){}
	vector(size_type n,const T& value){
		fill_initialize(n,value);
	}
	vector<int n,const T& value>{
		fill_initialize(n,value);
	}
	vector<long n,const T& value>{
		fill_initialize(n,value);
	}
	explicit vector(size_type n){
		fill_initialize(n,T());//填充默认值
	}

	~vector(){
		destroy(start,finish);  //全局函数
		deallocate();              //vector的一个member function
	}

	reference front(){return *begin();}
	reference back(){
		return *(end()-1);  //back():最后一个元素,end():最后一个元素的下一个位置
	}

	//将元素插入至最尾端
	void push_back(const T& x) {
		if(finish != end_of_storage){ //如果还有备用空间
			construt(finish,x); //全局函数
			++finish;
		}
		else //否则,扩充空间(重新配置、移动数据、移动原空间)
			insert_aux(end(),x);  //member function of vector
	}

	//将最尾端元素取出,并调整大小
	void pop_back(){  
		--finish;
		destroy(finish);  //全局函数
	}

	//清除[first,last)中的所有元素
	iterator erase(iterator first,iterator last){
		iterator i = copy(last,finish,first);
		destroy(i,finish);
		finish = finish -(last-first);
		return first;
	}

	//清除某位置上的元素
	iterator erase(iterator position){
		if(position + 1 != end()) //若是不尾元素
			copy(position+1,finish,position); //后续元素往前移动
		--finish;
		destroy(finish);
		return position;
	}

	void clear(){
		erase(begin(),end());
	}

	void resize(size_type new_size,const T& x){
		if(new_size<size())
			erase(begin()+new_size,end());
		else
			insert(end(),new_size - size(),x);
	}

	void resize(size_type new_size){
		resize(new_size,T()); //填充默认值
	}

protected:
	//配置空间并填满内容
	iterator allocate_and_fill(size_type n,const T& x){
		iterator result = data_allocator::allocate(n); //配置n个空间
		//全局函数,根据第一参数的类型特性(type trait),
		//决定使用算法fill_n()或反复调用construct
		uninitialized_fill_n(result,n,x); 
		return result;
	}
};<span style="color:#008000;">
</span>


template<class T,class Alloc>
void vector<T,Alloc>::insert_aux(iterator position,const T& x){
	if(finish != end_of_storage){ //还有备用空间
		//在备用空间起始处构造一个元素,并以vector最后一个元素值为其初值
		construct(finish,*(finish-1));
		++finish;
		T x_copy = x;
		copy_backward(position,finish-2,finish-1);
		*position = x_copy;
	}
	else{ //已无备用空间
		//配置原则:如果原大小为0,则配置为1
		//如果原大小不为0,则配置原大小的两倍
		const size_type old_size = size();
		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);
			//为新元素设定初值x
			construct(new_finish,x);
			//调整水位
			++new_finish;
			//将原vector的备用空间中的内容也忠实拷贝过来
			new_finish = uninitialized_copy(position,finish,new_finish);
		}
		catch (/*CMemoryException* e*/)
		{
			destroy(new_start,new_finish);
			data_allocator::deallocate(new_start,len);
			throw;
		}

		//析构并释放原vector
		destroy(begin(),end());
		deallocate();

		//调整迭代器,指向新vector
		start = new_start;
		finish = new_finish;
		end_of_storage = new_start+len;
	}
}


template<class T,class Alloc>
void vector<T,Alloc>::insert(iterator position,size_type n,const T& x){
	if(n!=0){
		if(size_type(end_of_storage-finish) >= n){
			//备用空间大于等于“新增元素个数”
			T x_copy = x;
			//计算插入点之后现有元素个数
			const size_type elem_after = finish - position;
			iterator old_finish = finish;
			if(elem_after>n){
				//"插入点之后的现有元素个数" 大于 "新增元素个数"
				uninitialized_copy(finish-n,finish,finish);
				finish +=n; //将vector尾端标记后移
				copy_backward(position,old_finish-n,old_finish);
				//从插入点开始填入新值
				fill(position,position+n,x_copy);
			}
			else{
				//"插入点之后的现有元素个数" 小于等于 "新增元素个数"
				uninitialized_fill_n(finish,n-elem_after,x_copy);
				finish += n-elem_after;
				uninitialized_copy(position,old_finish,finish);
				finish += elem_after;
				fill(position,old_finish,x_copy);
			}
		}
		else{
			//备用空间小于“新增元素个数”
			//首先决定新长度:旧长度的两倍,或旧长度+新增元素个数
			const size_type old_size = size();
			const size_type len = old_size + max(old_size,n);

			//以下配置新的vector空间
			iterator new_start = data_allocator::allocate(len);
			iterator new_finish = new_start;
			_STL_TRY{
				new_finish = uninitialized_copy(start,position,new_start);
				new_finish = uninitialized_fill_n(new_finish,n,x);
				new_finish = uninitialized_copy(position,finish,new_finish);
			}
#ifdef _STL_USE_EXCEPTIONS
			catch(){
				destroy(new_start,new_finish);
				data_allocator::deallocate(new_start,len);
				throw;
			}
#endif

			//以下清楚并释放旧的vector
			destroy(start,finish);
			deallocate();
			//以下调整水位标记
			start = new_start;
			finish = new_finish;
			end_of_storage = new_start+len;
		}
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值