顺序容器vector

顺序容器vector

概述

  • vector与array:数据安排和操作方式相似,但array是静态空间,一旦配置了就不能改变,除非用户自己生成空间。vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。

vector的关键在于其对大小的控制以及重新配置时的数据搬移效率

vector的迭代器

由于vector维护的是一个连续线性空间,所以不论元素类别,普通指针都可以作为vector的迭代器而满足必要条件,包括随机存取、操作符(*、->、++,–,+,-,+=,-=)等操作行为。
vector提供的是random access iterators。

typedef value_type* iterator; //value_type是元素类型

vector容量扩充

线性连续空间,以两个迭代器startfinish分别指向配置得来的连续空间中目前已使用的范围,并以迭代器end_of_storage指向整块连续空间(含备用空间)的尾端。
为了降低空间配置时的速度成本, vector实际配置的大小可能比客户端需求量更大一些,以备将来可能的扩充。

根据vs2017的环境(c++17),若需要空间大于当前capacity的1.5倍,则扩充为需要空间大小,反之扩充为capacity的1.5倍。以下为capacity增长代码:

size_type _Calculate_growth(const size_type _Newsize) const{
// given _Oldcapacity and _Newsize, calculate geometric growth
	const size_type _Oldcapacity = capacity();//vector对应的容量
	if (_Oldcapacity > max_size() - _Oldcapacity / 2){
		return (_Newsize);	// geometric growth would overflow
	}
	const size_type _Geometric = _Oldcapacity + _Oldcapacity / 2;
	if (_Geometric < _Newsize){
		return (_Newsize);	// geometric growth would be insufficient
	}
	return (_Geometric);	// geometric growth is sufficient
}

vector插入元素

(以下内容参考c++17源码)
push_back调用emplace_back

template<class... _Valty> 
	decltype(auto) emplace_back(_Valty&&... _Val){
		// insert by perfectly forwarding into element at end, provide strong guarantee
		if (_Has_unused_capacity()){
			//如果当前capacity足够,则直接插入
			_Emplace_back_with_unused_capacity(_STD forward<_Valty>(_Val)...);
		}
		else{	// reallocate
			const size_type _Oldsize = size();
			if (_Oldsize == max_size())	{ _Xlength(); }
			const size_type _Newsize = _Oldsize + 1;
			const size_type _Newcapacity = _Calculate_growth(_Newsize);//需要扩充的容量
			bool _Emplaced = false;
			const pointer _Newvec = this->_Getal().allocate(_Newcapacity);//分配需要容量的内存
			_Alty& _Al = this->_Getal();
			
			//在新内存空间中构造变量
			_TRY_BEGIN
			_Alty_traits::construct(_Al, _Unfancy(_Newvec + _Oldsize), _STD forward<_Valty>(_Val)...);
			_Emplaced = true;
			_Umove_if_noexcept(this->_Myfirst(), this->_Mylast(), _Newvec);
			_CATCH_ALL
			if (_Emplaced){
			//若已经覆盖好新的内存,则销毁旧的变量
				_Alty_traits::destroy(_Al, _Unfancy(_Newvec + _Oldsize));
			}
			//销毁旧的内存空间,如果没有覆盖成功,则把新内存空间销毁
			_Al.deallocate(_Newvec, _Newcapacity);
			_RERAISE;
			_CATCH_END
	
			_Change_array(_Newvec, _Newsize, _Newcapacity);
		}
		#if _HAS_CXX17
		return (this->_Mylast()[-1]);
		#endif /* _HAS_CXX17 */
	}

insert(插入一个元素)调用emplace函数

vector源码摘要

(以下内容参考stl源码剖析,和最新版vector(c++17)有所出入)

//alloc 是SGI STL的空间配置器
template <class T, class Alloc = alloc>
class vector{
public:
	typedef T value_type;
	typedef value_type*  pointer;
	typedef value_type*  iterator; //vector的迭代器是普通指针
	typedef value_type&  reference;
	typedef size_t 		 size_type;
protected:
	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 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); }
	
	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() ); }
	//explicit 阻止隐式转换,通过T类型的默认初始化函数进行初始化
	
	~vector(){
		destroy(start, finish);//全局函数
		deallocate(); 
	}
	reference front(){ return *begin(); }//第一个元素
	reference back(){ return *( end() - 1 ); } // 最后一个元素
	void push_back( const T& x){
		if (finish != end_of_storage ){
			construct( finish, x ); //全局函数
			++finish;
		}else
			insert_aux( end(), x );
	}
	void pop_back(){
		--finish;
		destroy( finish ); // 全局函数	
	}

	iterator erase ( iterator position ){
		if (position + 1 != end())
			copy(position+1, finish, position); // 后续元素往前移动
		--finish;
		destroy ( finish );
		return position;
	}

	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() ); }
	void clear() { erase( begin(), end() ); }

protected:
	iterator allocate_and_fill( size_type n, const T& x ){
		iterator result = data_allocator::allocate(n);
		uninitialized_fill_n( result, n, x); //全局函数
		return result;
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值