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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-02 14:27:45