STL源码剖析vector

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


vector的定义

vector可以理解为一个动态数组,他能够自适应地变更自己的大小。总之就是很厉害。

看看SGI vector的相关定义代码

template <class T, class Alloc = alloc>
class vector{
public:
//通过模板推断
	typedef T			value_type;
	typedef T*			pointer;
	typedef T*			iterator;
	typedef T&			reference;
	typedef size_t		size_type;
	typedef ptrdiff_t	difference_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 != nullptr){
		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()const {return start;}
	iterator end() {return finish;}
	//size_type()这种是新时代的c++的强转,应该更潮更in
	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 value_type& value){
		fill_initialize(n, value);
	}
	vector(int n, const value_type& value){
		fill_initialize(n, value);
	}
	vector(long n, const value_type& value){
		fill_initialize(n, value);
	}
	explicit vector(size_type n){
		fill_initialize(n, value_type());
	}
	
	~vector(){
		destroy(start, finish);
		deallocate();
	}
	
	reference front() {return *begin();}
	reference back() {return *(end() - 1);}
	
	void push_back(const T& x){
		if(end() != end_of_storage){
			construct(end(), x);
			++finish;
		}else{
			insert_aux(end(), x);
		}
	}
	
	void pop_back(){
		if(end() != begin()){
			--finish;
			destroy(end())
		}
	}
	
	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());
			finish = new_size;
		}else{
			insert(end(), new_size - size(), x);
		}
	}
	void resize(size_type new_size) {resize(new_sizse, T());}
	void clear(){erase(begin(), end());}
protected:
	iterator allocate_and_fill(size_type n, const value_type& value){
		iterator result = data_allocator::allocate(n);
		uninitialized_fill_n(result, n, x);
		return result;
	}
	

上面可以看出vector的功能,他能存储东西,push_back实现了存储,他能动态分配存储大小,于是他实现了allocate和deallocate来进行内存管理,同时他还有一些更细节的功能如resize,但是总体看下来是很友好易理解的。


提示:以下是本篇文章正文内容,下面案例可供参考

vector的空间分配算法

从使用者的角度,我们所需要的容器不应该是一个静态大小的,他应该是能在存储小数据量数据时不开太大的内存空间,又有存储大量数据量的能力,于是vector的空间扩充算法十分重要。

template<class T, class Alloc>
void vector<T, Alloc>::insert_aux(iterator position, const T& x){
	if(finish != end_of_storage){
		construct(finish, *(finish - 1));
		T x_copy = x;
		//不知道为什么这么写啊啊啊啊,为什么不直接用copy呢
		//懂了,copy会有覆盖发生(在本例子中),而将最后一个元素先构造出来,在逆序赋值不会发生覆盖
		//可以自己写个小例子测试一下
		copy_backward(position, finish - 2, finish - 1);
		*position = x_copy;
		++finish;
	}else{
		const size_type old_size = size();
		const size_type new_size = old_size == 0 ? 1 : 2 * old_size;
		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;
			//注意这里算法的细节,以及如何保证线程安全
			new_finish = uninitialized_copy(position, finish, new_finish);
		}
		catch(...)(
			//destroy管理的是析构
			destroy(new_start, new_finish);
			data_allocator::deallocate(new_start, len)throw
		}
	}
	destroy(begin(), end());
	deallocate();
	start = new_start;
	finish = new_finish;
	end_of_storage = new_start + len;
}

空间扩展算法也很简单,就是遇到不够的时候扩大两倍。扩大的时候是新建空间而不是在原空间上新增。算法细节要注意元素位置以相关回滚的操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值