码迷,mamicode.com
首页 > 其他好文 > 详细

STL(3)---<vector>

时间:2015-08-11 10:07:42      阅读:95      评论:0      收藏:0      [点我收藏+]

标签:

    vector是STL中最常见的容器,它是一种顺序容器,支持随机访问。vector是一块连续分配的内存,从数据安排的角度来讲,和数组极其相似,不同的地方就是:数组是静态分配空间,一旦分配了空间的大小,就不可再改变了;而vector是动态分配空间,随着元素的不断插入,它会按照自身的一套机制不断扩充自身的容量。

   vector的扩充机制:按照容器现在容量的一倍进行增长。vector容器分配的是一块连续的内存空间,每次容器的增长,并不是在原有连续的内存空间后再进行简单的叠加,而是重新申请一块更大的新内存,并把现有容器中的元素逐个复制过去,然后销毁旧的内存。这时原有指向旧内存空间的迭代器已经失效,所以当操作容器时,迭代器要及时更新。

vector数据结构,采用的是连续的线性空间,属于线性存储。他采用3个迭代器_First、_Last、_End来指向分配来的线性空间的不同范围

技术分享

下面是我提取出的一些源码和自己的理解

#include "allocator.h"

//vector容器是一个模板类,可以存放任何类型的对象(但必须是同一类对象)vector对象可以在运行时高效地添加元素,并且vector中元素是连续存储的。	
//这里我所提出的源码中没有const迭代器和反向迭代器,而且后边对于vector的一个特化的范例bool型也没有列出

namespace w
{	// TEMPLATE CLASS vector
	
	template<class _Ty, class _A = allocator<_Ty> >
		class vector {
public:
	typedef vector<_Ty,_A> _Myt;//只在类中有效的类型重定义
	
public:
	typedef _A allocator_Type;
	typedef _A::difference_type difference_Type;
	typedef _A::pointer _Tptr;
	//	typedef _A::const _Ctptr;
	typedef _A::reference reference;
	//	typedef _A::const_reference const_reference;
	typedef _A::value_type value_type;
	typedef _Tptr iterator;//对于向量无需对指针进行包装组成迭代器,指针本省作为迭代器
	//	typedef _Ctptr const_iterator;
	
	explicit vector(const _A& _Al = _A())//构造函数产生默认的vector对象但是不能隐式类型转换
		: allocator(_Al), _First(0), _Last(0), _End(0) {}
	explicit vector(size_t _N, const _Ty& _V = _Ty(),//产生_N个值为_V的对象
		       const _A& _Al = _A())
		       : allocator(_Al)
	{_First = allocator.allocate(_N, (void *)0);
	_Ufill(_First, _N, _V);
	_Last = _First + _N;
	_End = _Last; }
	vector(const _Myt& _X)//拷贝构造函数
		: allocator(_X.allocator)
	{_First = allocator.allocate(_X.size(), (void *)0);
	_Last = _Ucopy(_X.begin(), _X.end(), _First);
	_End = _Last; }
	typedef iterator _It;
	vector(_It _F, _It _L, const _A& _Al = _A())//用一段数据来初始化
		: allocator(_Al), _First(0), _Last(0), _End(0)
	{insert(begin(), _F, _L); }
	~vector()
	{
	_Destroy(_First, _Last);
	allocator.deallocate(_First, _End - _First);
	_First = 0, _Last = 0, _End = 0; 
	}
	_Myt& operator=(const _Myt& _x)//赋值函数
	{
		if(&_x != this)
		{
			if(_x.size() <= size())
			{
				iterator _s=copy(_x.begin(),_x.end(),_First);
				_Destroy(_s,_Last);
				_Last =_First + _x.size();
			}
			else if(_x.size() <= _x.capacity())
			{
				iterator _s = _x.begin()+size();
				copy(_x.begin(), _s, _First);
				_Ucopy(_s, _x.end(), _Last);
			     _Last = _First + _x.size();
			}
		}
		return *this;
	}
	void reserve(size_t _N)// 确保capacity() >= _N
	{
	if (capacity() < _N)//小于就重新分配之后将原数据复制过来
	{
	 iterator _S = allocator.allocate(_N, (void *)0);
	_Ucopy(_First, _Last, _S);
	_Destroy(_First, _Last);
	allocator.deallocate(_First, _End - _First);
	_End = _S + _N;
	_Last = _S + size();
	_First = _S;
	}
	}
	size_t capacity() const// 容器能够存储的元素个数,有:capacity() >= size()  
	{return (_First == 0 ? 0 : _End - _First); }
	iterator begin()
	{return (_First); }
	
	iterator end()//注意是返回一个指向被控序列末端的下一个位置的迭代器
	{return (_Last); }
	///////////reverse//////////////
	void resize(size_t _N, const _Ty& _X = _Ty())// 确保返回后,有:size() == n;如果之前size()<n,那么用元素x的值补全。
	{if (size() < _N)
	insert(end(), _N - size(), _X);
	else if (_N < size())
		erase(begin() + _N, end()); }
	size_t size() const // 返回容器中元素个数
	{return (_First == 0 ? 0 : _Last - _First); }
	size_t max_size() const // 返回容器能容纳的最大元素个数
	{return (allocator.max_size()); }
	bool empty() const// 如果为容器为空,返回true;否则返回false
	{return (size() == 0); }
	_A get_allocator() const//返回空间配置器
	{return (allocator); }
	reference at(size_t _P)const//这个使用起来比重载的[]更加安全
	{  // 返回下标为pos的元素的引用;如果下标不正确,则抛出异常out_of_range
		if(size()<=_P)//这里要有等于相当于判断数组是否越界的
		{
			_Xran();//抛出异常
		}
		return (*(begin()+_P));
	}
	reference operator[](size_t _P)// 返回下标为pos的元素的引用(下标从0开始;如果下标不正确,则属于未定义行为
	{return (*(begin() + _P)); }
	reference front() // 返回容器中第一个元素的引用(容器必须非空)
	{return (*begin()); }
	
	reference back()// 返回容器中最后一个元素的引用(容器必须非空)
	{return (*(end() - 1)); }
	void push_back(const _Ty& _X)// 向容器末尾添加一个元素    
	{insert(end(), _X); }
	void pop_back()  // 弹出容器中最后一个元素(容器必须非空)
	{erase(end() - 1); }
	void assign(_It _F, _It _L)
	{erase(begin(), end());
	insert(begin(), _F, _L); }
	void assign(size_t _N, const _Ty& _X = _Ty()) // 赋值,用指定元素序列替换容器内所有元素
	{erase(begin(), end());
	insert(begin(), _N, _X); }
	// 注:下面的插入和删除操作将发生元素的移动(为了保持连续存储的性质),所以之前的迭代器可能失效
	iterator insert(iterator _P,const _Ty&_x=_Ty())//插入后并返回插入的那个数据的地址
	{ // 在插入点元素之前插入元素(或者说在插入点插入元素)
		size_t tmp =_P -begin();
		insert(_P,1,_x);
		return(begin()+tmp);
	}
	void insert(iterator _P,size_t _N,const _Ty&_x=_Ty())//从一个位置开始向后面插入_N个相同的数据_x
	{// 注意迭代器可能不再有效(可能重新分配空间)
		if(_End - _First < _N)//如果创建的空间容量中(还未用的空间和已经用的)不足以满足_N个数据的存储
		{
			size_t _M =size()+(_N<size() ? size():_N);//分配的内存至少是原来的一倍
			iterator _s= allocator.allocate(_M,(void*)0);//分配内存
			iterator _q =_Ucopy(_First,_P,_s);//原来的数据拷贝到新的内存中
			//这里_Ucopy()返回的是将原数据拷贝完后的下一个内存空间的迭代器
			
			_Ufill(_q,_N,_x);//用_N个_x填满拷贝完原数据后余下的内存空间
			_Destroy(_First,_Last);//析构原来的对象
			allocator.deallocate(_First,_End -_First);//释放原来的内存,此时_End还指向原来的内存容量处
			
			_End = _s+_M;//把_End的指向改变一下
			_Last = _s+size()+_N;
			
			_First =_s;
		}
		else if(_Last - _P < _N)//此时要在原数据的_P到_End之间插入_N个数据,就是不必要再冲洗分配内存
		{
			_Ucopy(_P,_Last,_P+_N);//将原来的数据中_P到_last之间有的数据向后移动_N位
			_Ufill(_Last,_N-(_Last-_P),_x);//首先解释_P有可能指向原来的数据的某一个位置,但是_P到了_last之间的数据
			//不够_N所以会向外走,这就话就是用_x来填满外边的这些个数位置
			fill(_P,_Last,_x);//把里面的用_x填满
			
			_Last += _N;//注意哟,就是 _last =_last+_N;
			
		}
		else if(0<_N)//这个就是一开始没有数据的时候,要分配空间的
		{
			_Ucopy(_Last - _N,_Last,_Last);
			copy_backward(_P,_Last-_N,_Last);
			fill(_P,_P+_N,_x);
			_Last += _N;
		}
	}
	
	void insert(iterator _P,_It _F,_It _L)//在_P迭代器所指的空间的后边插入后边两个迭代器的数据范围
	{
		size_t _M =0;
		_Distance(_F,_L,_M);//计算两个迭代器之间的元素个数
		if (_End - _Last < _M)
		{
			size_t _N = size() + (_M < size() ? size() : _M);
			iterator _S = allocator.allocate(_N, (void *)0);
			iterator _Q = _Ucopy(_First, _P, _S);//原来的数据复制到新的空间
			_Q = _Ucopy(_F, _L, _Q);//再把_F 到_L所指的数据复制到新的空间上
			_Ucopy(_P, _Last, _Q);//再把_P 到_last的原来的数据复制到新的空间
			
			_Destroy(_First, _Last);
			allocator.deallocate(_First, _End - _First);
			_End = _S + _N;
			_Last = _S + size() + _M;
			_First = _S;
		}
		else if (_Last - _P < _M)
		{
			_Ucopy(_P, _Last, _P + _M);//复制相当于把原来的数据后移每次都是创建一个节点
			_Ucopy(_F + (_Last - _P), _L, _last);//先把后半段复制过来
			copy(_F, _F + (_Last - _P), _P);//再把前半段复制过来
			_Last += _M;
		}
		else if (0 < _M)
		{
			_Ucopy(_Last - _M, _Last, _Last);
			copy_backward(_P, _last - _M, _Last);
			copy(_F, _L, _P);
			_Last += _M; 
		}
	}
	iterator erase(iterator _P) // 删除指定元素,并返回删除元素后一个元素的位置(如果无元素,返回end())
	{copy(_P + 1, end(), _P);
	_Destroy(_Last - 1, _Last);
	--_Last;
	return (_P); }

	iterator erase(iterator _F, iterator _L)// 注意:删除元素后,删除点之后的元素对应的迭代器不再有效。
	{iterator _S = copy(_L, end(), _F);
	_Destroy(_S, end());
	_Last = _S;
	return (_F); }
	void clear()
	{erase(begin(), end()); }
	bool _Eq(const _Myt& _X) const//判断相等
	{return (size() == _X.size()
	&& equal(begin(), end(), _X.begin())); }

	bool _Lt(const _Myt& _X) const//判断不等
	{return (lexicographical_compare(begin(), end(),
	_X.begin(), _X.end())); }
	void swap(_Myt& _X)//判断是不是使用的同一个空间配置器
	{                   //交换对象
		if (allocator == _X.allocator)
		{
			std::swap(_First, _X._First);
			std::swap(_Last, _X._Last);
			std::swap(_End, _X._End); 
		}
		else//否则直接将两个对象交换
		{
			_Myt _Ts = *this; 
			*this = _X, 
				_X = _Ts; 
		}
	}
	friend void swap(_Myt& _X, _Myt& _Y)
	{_X.swap(_Y); }
protected:
	void _Destroy(iterator _F, iterator _L)
	{for (; _F != _L; ++_F)
	allocator.destroy(_F); }
	iterator _Ucopy(iterator _F, iterator _L,
		iterator _P)
	{for (; _F != _L; ++_P, ++_F)
	allocator.construct(_P, *_F);
		return (_P); }
	void _Ufill(iterator _F, size_t _N, const _Ty &_X)
		{for (; 0 < _N; --_N, ++_F)
			allocator.construct(_F, _X); }
	void _Xran() const
		{_THROW(out_of_range, "invalid vector<T> subscript"); }
	
	_A allocator;
	iterator _First, _Last, _End;
        //_First指向使用空间的头部,
        //_last指向使用空间大小(size)的尾部
        //_End指向空间容量(capacity)的尾部
 };

//	vector对象的比较(非成员函数)
		
  // 针对vector对象的比较有六个比较运算符:
  //operator==、operator!=、operator<、operator<=、operator>、operator>=。
template<class _Ty, class _A> inline
	bool operator==(const vector<_Ty, _A>& _X,
		const vector<_Ty, _A>& _Y)
	{return (_X._Eq(_Y)); }
template<class _Ty, class _A> inline
	bool operator!=(const vector<_Ty, _A>& _X,
		const vector<_Ty, _A>& _Y)
	{return (!(_X == _Y)); }
template<class _Ty, class _A> inline
	bool operator<(const vector<_Ty, _A>& _X,
		const vector<_Ty, _A>& _Y)
	{return (_X._Lt(_Y)); }
template<class _Ty, class _A> inline
	bool operator>(const vector<_Ty, _A>& _X,
		const vector<_Ty, _A>& _Y)
	{return (_Y < _X); }
template<class _Ty, class _A> inline
	bool operator<=(const vector<_Ty, _A>& _X,
		const vector<_Ty, _A>& _Y)
	{return (!(_Y < _X)); }
template<class _Ty, class _A> inline
	bool operator>=(const vector<_Ty, _A>& _X,
		const vector<_Ty, _A>& _Y)
	{return (!(_X < _Y)); }


}
//allocator.h

//#include <cstdlib>//包含ptrdiff_t(int),size_t
//#include <new>   //包含 placement new
namespace k
{ 
	// TEMPLATE FUNCTION _Allocate
	template<class _Ty> inline 
		_Ty *_Allocate(ptrdiff_t _N, _Ty *)
	{
		if (_N < 0)
			_N = 0;
		return ((_Ty *)operator new((ptrdiff_t)_N * sizeof (_Ty))); 
	}
	
	// TEMPLATE FUNCTION _Construct
	template<class _T1, class _T2> inline
		void _Construct(_T1  *_P, const _T2& _V)
	{   new ((void*)_P) _T1(_V); }//placement new,调用T1的构造函数构造对象
	     //new(_P) _T1(value);
	
	// TEMPLATE FUNCTION _Destroy
	
	template<class _Ty> inline
	void _Destroy(_Ty *_P)
	{   _P->~Ty(); }
	// TEMPLATE CLASS allocator

	template<class _Ty>
		class allocator{
public:
	typedef size_t        size_type;
	typedef ptrdiff_t     difference_type;
	typedef _Ty*          pointer;
   //typedef const _Ty*    const_pointer;
	typedef _Ty&          reference;
	//typedef const _Ty&    const_reference;
	typedef _Ty           value_type;
	

	pointer address(reference _X) const
	{return (&_X); }//返回对象地址
//	const_pointer address(const_reference _X) const
//	{return (&_X); } //返回常对象地址
	pointer allocate(size_type _N, const void *)
	{return (_Allocate((difference_type)_N,(pointer)0)); }
	char *_Charalloc(size_type _N)
	{return (_Allocate((difference_type)_N,(char*)0)); }
	void deallocate(void *_P, size_type)
	{operator delete(_P); }
	void construct(pointer _P, const _Ty& _V)
	{_Construct(_P, _V); }
	void destroy(pointer _P)
	{_Destroy(_P); }
	size_type max_size() const
	{
		size_type _N = (size_type)(-1) / sizeof (_Ty);//类型除以-1是该类型中所能表示的最大无符号值
		return (0 < _N ? _N : 1); 
	}
	
	};
	
}
下面是vector的一些用法:
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector< int > a ;   
    for(int i=0;i<10;++i)
	{
		a.push_back(i);
	}
	for( i = 0; i < a.size(); i++ )//v.size() 表示vector存入元素的个数	
	{
		cout << a.at(i) << "  "; //把每个元素显示出来
	} 
	cout<<endl;
	for( i=0;i<a.size();i++)
	{
		cout<<a[i]<<" ";
	}
cout<<endl;
	vector<int> vv;
	vv.reserve(10);//reserve()分配了10个int型的空间,但并没有初始化
	for( i=0; i<7; i++)
		vv.push_back(i);
	try	
	{
		int iVal1 = vv[7];  // not bounds checked - will not throw
		int iVal2 = vv.at(7); // bounds checked - will throw if out of range	
	}
	catch(const exception& e)	
	{	
		cout << e.what();		
	}
cout<<endl;
	vector<int>::iterator iter;
	for(iter = a.begin(); iter != a.end();++iter)
	{
		cout<<*iter<<" ";
	}
	cout<<endl;
 //建立一个10行的列可变的二维数组

  vector<vector<int> > arr(10,vector<int>(0));//vector<int>(0)是对vector初始化,否则不能对vector存入元素。
   for(i=0;i<10;++i)
   {
	   for(int j=0;j<9;++j)
	   {
		   arr[j].push_back(i);
	   }
   }

   for(i=0;i<10;++i)
   {
	   for(int j=0;j<arr[i].size();++j)
	   {
            cout<<arr[i][j]<<" ";
	   }
   }
	cout<<endl;
   //建立一个行列都能变化的数组

   vector<vector<int> > arry;
   vector<int> n;

   for(i=0;i<10;++i)
   {
	   arry.push_back(n);//要对每一个vector初始化,否则不能存入元素。
    for(int j=0;j<9;++j)
	{
		arry[i].push_back(j);
	}
   
   }
   for(i=0;i<10;++i)
   {
	   for(int j=0;j<arry[i].size();++j)
	   {
		   cout<<arry[i][j]<<" ";
	   }
   }

   cout<<endl;

    vector<int> v(5, 1);
	v.insert(v.begin() + 3, 1, 2);
    v.insert(v.begin() + 4, 1, 3);
    v.insert(v.begin() + 5, 1, 4);
	
    v.insert(v.begin() + 6, 1, 5);
	
    cout<<"> After insert"<<endl;
    for( i = 0; i < v.size(); ++i)
        cout<<v[i]<<" ";
	cout<<endl;
	vector<int>::iterator it1 = v.erase(v.begin() + 3, v.begin() + 6);//删除的是第4,5,6三个元素
    cout<<"> After erase"<<endl;
    for( i = 0; i != v.size(); ++i)//*it1 =5;
        cout<<v[i]<<" ";
	cout<<endl;
		return 0;
}





版权声明:本文为博主原创文章,未经博主允许不得转载。

STL(3)---<vector>

标签:

原文地址:http://blog.csdn.net/kai8wei/article/details/47405713

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!