(1)Array是静态空间,大小一旦确定就不能改变。
Vector是动态空间,每增加一个元素可以自动扩充空间。
(2)Vector维护的是一个连续线性空间,支持随机存取。
为了降低空间配置时的速度成本,vector实际配置的大小可能比客户端需求的量更大一些,以备将来可能的扩充。这便是容量(capacity)的观念。换句话说,一个vecotr的容量永远大于或等于其大小。一旦容量等于大小,便是满载,下次再有新增元素,整个vector就得另觅居所。
新增加元素时,如果超过当时的容量,则容量会扩充至两倍。如果两倍容量仍不足,就扩充至足够大的容量。
容量的扩张必须经历“重新配置、元素移动、释放原空间”等过程。
(3)vector缺省使用alloc作为空间配置器,并据此另外定义一个data_allocator,为的是更方便以元素大小为配置单位。
//simple_alloc 是SGT STL的空间配置器
typedef simple_alloc<value_type,Alloc> data_allocator;
于是,data_allocator::allocate(n) 表示配置n个元素空间。
(4)动态增加大小,并不是在原空间之后持续新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原大小的两倍另外配置一块较大空间,然后将原内容拷贝过来,之后才开始在原内容之后构造新元素,并释放原空间。
因此对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了。
//alloc 是SGI STL的空间配置器
template<class T,class Alloc = alloc>
class vector{
typedef T value_type;
typedef value_type* pointer;
typedef value_type* iterator; //vector的迭代器是普通指针
typedef value_type& reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
protected:
//simple_alloc 是SGT STL的空间配置器
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 insert(iterator position,size_type n,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);
}
//construct function
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());//填充默认值
}
~vector(){
destroy(start,finish); //全局函数
deallocate(); //vector的一个member function
}
reference front(){return *begin();}
reference back(){
return *(end()-1); //back():最后一个元素,end():最后一个元素的下一个位置
}
//将元素插入至最尾端
void push_back(const T& x) {
if(finish != end_of_storage){ //如果还有备用空间
construt(finish,x); //全局函数
++finish;
}
else //否则,扩充空间(重新配置、移动数据、移动原空间)
insert_aux(end(),x); //member function of vector
}
//将最尾端元素取出,并调整大小
void pop_back(){
--finish;
destroy(finish); //全局函数
}
//清除[first,last)中的所有元素
iterator erase(iterator first,iterator last){
iterator i = copy(last,finish,first);
destroy(i,finish);
finish = finish -(last-first);
return first;
}
//清除某位置上的元素
iterator erase(iterator position){
if(position + 1 != end()) //若是不尾元素
copy(position+1,finish,position); //后续元素往前移动
--finish;
destroy(finish);
return position;
}
void clear(){
erase(begin(),end());
}
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()); //填充默认值
}
protected:
//配置空间并填满内容
iterator allocate_and_fill(size_type n,const T& x){
iterator result = data_allocator::allocate(n); //配置n个空间
//全局函数,根据第一参数的类型特性(type trait),
//决定使用算法fill_n()或反复调用construct
uninitialized_fill_n(result,n,x);
return result;
}
};<span style="color:#008000;">
</span>
template<class T,class Alloc>
void vector<T,Alloc>::insert_aux(iterator position,const T& x){
if(finish != end_of_storage){ //还有备用空间
//在备用空间起始处构造一个元素,并以vector最后一个元素值为其初值
construct(finish,*(finish-1));
++finish;
T x_copy = x;
copy_backward(position,finish-2,finish-1);
*position = x_copy;
}
else{ //已无备用空间
//配置原则:如果原大小为0,则配置为1
//如果原大小不为0,则配置原大小的两倍
const size_type old_size = size();
const size_type len = old_size !=0 ? 2*old_size : 1;
iterator new_start = data_allocator::allocate(len); //实际配置
iterator new_finish = new_start;
try
{
//将原vector的内容拷贝到新vector
new_finish = uninitialized_copy(start,position,new_start);
//为新元素设定初值x
construct(new_finish,x);
//调整水位
++new_finish;
//将原vector的备用空间中的内容也忠实拷贝过来
new_finish = uninitialized_copy(position,finish,new_finish);
}
catch (/*CMemoryException* e*/)
{
destroy(new_start,new_finish);
data_allocator::deallocate(new_start,len);
throw;
}
//析构并释放原vector
destroy(begin(),end());
deallocate();
//调整迭代器,指向新vector
start = new_start;
finish = new_finish;
end_of_storage = new_start+len;
}
}
template<class T,class Alloc>
void vector<T,Alloc>::insert(iterator position,size_type n,const T& x){
if(n!=0){
if(size_type(end_of_storage-finish) >= n){
//备用空间大于等于“新增元素个数”
T x_copy = x;
//计算插入点之后现有元素个数
const size_type elem_after = finish - position;
iterator old_finish = finish;
if(elem_after>n){
//"插入点之后的现有元素个数" 大于 "新增元素个数"
uninitialized_copy(finish-n,finish,finish);
finish +=n; //将vector尾端标记后移
copy_backward(position,old_finish-n,old_finish);
//从插入点开始填入新值
fill(position,position+n,x_copy);
}
else{
//"插入点之后的现有元素个数" 小于等于 "新增元素个数"
uninitialized_fill_n(finish,n-elem_after,x_copy);
finish += n-elem_after;
uninitialized_copy(position,old_finish,finish);
finish += elem_after;
fill(position,old_finish,x_copy);
}
}
else{
//备用空间小于“新增元素个数”
//首先决定新长度:旧长度的两倍,或旧长度+新增元素个数
const size_type old_size = size();
const size_type len = old_size + max(old_size,n);
//以下配置新的vector空间
iterator new_start = data_allocator::allocate(len);
iterator new_finish = new_start;
_STL_TRY{
new_finish = uninitialized_copy(start,position,new_start);
new_finish = uninitialized_fill_n(new_finish,n,x);
new_finish = uninitialized_copy(position,finish,new_finish);
}
#ifdef _STL_USE_EXCEPTIONS
catch(){
destroy(new_start,new_finish);
data_allocator::deallocate(new_start,len);
throw;
}
#endif
//以下清楚并释放旧的vector
destroy(start,finish);
deallocate();
//以下调整水位标记
start = new_start;
finish = new_finish;
end_of_storage = new_start+len;
}
}
}