深入理解vector

vector概述

vector的数据安排以及操作方式与array非常相似,两者的唯一差别在于空间的运用的灵活性,array是静态空间,一旦配置了就不能改变,vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素

vector的迭代器

vector维护的是一个连续线性空间,所以不论其元素型别为何,普通指针都可以作为vector的迭代器而满足所有必要条件,所以vector提供的是Random Access Iterators

template <class T,class Alloc=alloc>
class vector
{
	typedef T value_type;
	typedef value_type* iterator;
};

vector的数据结构

vector所采用的数据结构非常简单:线性连续空间。它以两个迭代器start和finish分别指向配置得来的连续空间中目前已被使用的范围,并以迭代器end_of_storage指向整块连续空间的尾端:

template <class T,class Alloc =alloc>
class vector
{
protected:
	iterator start;
	iterator finish;
	iterator end_of_storage;
};

运用start,finish,end_of_storage三个迭代器,便可轻易地提供首尾标示,大小,容量,空容器判断,注标([])运算子等功能

template <class T,class Alloc=alloc>
class vector
{
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);
	}
	reference front() 
	{
		return *begin();
	}
	reference back()
	{
	 	return *(end()-1);
	}
};

vector的构造与内存管理

vector提供许多constructs,其中一个允许我们指定空间大小及初值:

//构造函数,允许指定vector大小n和初值value
vector(size_type n,const T& value)
{
	fill_initialize(n,value);
}

//填充并予以初始化
void fill_initialize(size_type n,const T& value)
{
	start =allocte_and_fill(n,value);
	finish=start+n;
	end_of_storage=finish;
}
//配置而后填充
iterator allocate_and_fill(size_type n,const T& x)
{
	iterator result=data_allocator::allocate(n);
	unititalized_fill_n(result,n,x);
	return result;
}

当我们以push_back()将新元素插入到vector尾端时,该函数首先检查是否还有备用空间,如果有就直接在备用空间上构造元素,并调整迭代器finish,使vector变大,如果没有备用空间了,就扩充空间(重新配置,移动数据,释放空间)

void push_back(const T& x)
{
	if(finish!=end_of_storage)
	{
		construct(finish,x);
		++finish;
	}
	else
		insert_aux(end(),x);
}
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
	{
		const size_type old_size=size();
		const size_type len=old_size!=0?2*old_size:1;
		//以上配置原则:如果原大小为0,则配置1个元素大小
		//如果原大小不为0,则配置原大小的两倍
		//前半段用来放置原数据,后半段准备用来放置新数据
		iterator new_start=data_allocator::allocate(len);
		iterator new_finish=new_start;
		try
		{
			new_finish=uninitialized_copy(start,position,new_start);
			construct(new_finish,x);
			++new_finish;
			//将原vector的备用空间中的内容也忠实拷贝过来
			new_finish=uninitialized_copy(position,finish,new_finish);
		}
		catch(...)
		{
			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;	
	}
}

所谓的动态增加大小,并不是在原空间之后接续新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原大小的两倍另外配置一块较大空间,然后将原内容拷贝过来,然后才开始在原内容之后构造新元素,并释放原空间,因此,对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器都失效了

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;
}

在这里插入图片描述
下面是vector::insert()实现内容:

//从position开始,插入n个元素,元素初值为x
template <class T,class Alloc>
void vector<T,Alloc>::insert(iterator position,size_type n,const  T& x)
{
	if(n!=0)//当n!=0,才进行以下所有操作
	{
		if(size_type(end_of_storage-finish)>=n)//备用空间大于等于新增元素个数
		{
			T x_copy=x;
			const size_type elems_after=finish-position;
			iterator old_finish=finish;
			if(elems_after>n)//插入点之后的现有元素个数大于新增元素个数
			{
				uninitialized_copy(finish-n,finish,finish);
				finish+=n;
				copy_backward(position,old_finish-n,old_finish);
				fill(position,position+n,x_copy);
			}	
			else//插入点之后的现有元素个数小于等于新增元素个数
			{
				uninitialized_fill_n(finish,n-elems_after,x_copy);
				finish+=n-elems_after;
				uninitialized_copy(position,old_finish,finish);
				finsih+=elems_after;
				fill(position,old_finish,x_copy);			}
		}
	}
	else
	{
		//备用空间小于新增元素个数(那就必须配置额外的内存)
		//首先决定新长度:旧长度的两倍,或旧长度+新增元素个数
		const size_type old_size=size();
		const size_ype len=old_size+max(old_size,n);
		//以下配置新的vector空间
		iterartor new_start=data_allocator::allocate(len);
		iterator new_finish=new_start;
		_STL_TRY
		{
			//以下首先将旧vector的插入点之前的元素复制到新空间
			new_finish=uninitialized_copy(start,position,new_start);
			//以下再将新增元素填入新空间
			new_finish=uninitialized_copy_n(new_finish,n,x);
			new_finish=uninitialized_copy(psition,finish,new_finish);
			
		}
	}
#ifdef _STL_USE_EXCEPTIONS
	catch(...)
	{
		destroy(new_start,new_finish);
		data_allocator::deallocate(new_start,len);
		throw;
	}
#endif
	destroy(start,finish);
	deallocate();
	deallocate();
	start=new_start;
	finsih=new_finish;
	end_of_storage=new_start+len;
	}
  }	
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值