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