您的位置:首页 > 编程语言 > C语言/C++

C++ STL容器之vector的知识点及源码分析

2017-10-18 14:51 435 查看
vector的数据安排和array非常相似,array是静态空间,一旦配置就不能改变,如果要改变的话,首先要配置新的空间,把元素移过去,释放原来的空间。而vector模塑出个一dynamic array,随着元素加入,它的内部机制自行扩充空间(一旦vector的空间满载,内部机制会做出配置新空间、激动数据、释放旧空间的行为)。

1.vector的构造和析构函数 

vector<Elem>  c                                  //Default构造函数,产生空vector,没有元素

vector<Elem>  c(c2)   or  c=c2          //Copy构造函数,建立一个和c2同类型的vector,拷贝c2

vector<Elem>  c(n)                             //利用Default构造函数,生成大小为n的vector

vector<Elem>  c(n,elem)                   //生成大小为n的vector,每个元素值为elem

vector<Elem>  c(beg,end)                //建立一个vector,以[beg,end)作为元素值

vector<Elem>  c(initlist)  or c=initlist //建立一个vector,以初值列如{0 , 0,0,0}为初值

c.~vector()                                           //销毁所有元素,释放内存

2.vector的操作

c.empty()                                  c.begin()                                        c.push_back()
c.size()                                      c.end()                                            c.pop_back()
c.max_size()                            c.cbegin()                                       c.insert(pos,elem) //在pos之前插入元素,返回新元素的位置
c.capacity()                              c.cend()                                           c.insert(pos,n,elem) //插入n个元素,返回第一个新元素位置
c.reserve()                               c.rbegin()                                         c.insert(pos,beg,end)
c.shrink_to_fit()                        c.rend()                                            c.insert(pos,initlist)
==    !=   <     <=    >   >=          c.crbegin()                                        c.erase(pos)
c1.swap(c2)                              c.crend()                                          c.erase(beg,end)
c[下标]                                                                                                 c.clear()
c.at(下标)
c.front()     c.back() 

注:间接缩减vector容量的小窍门,使用swap交换两个vector内容,两者的容量也会互换。
template <typename T>
void shrinkCapacity(vector<T>& v)
{
vector<T> tmp(v);
v.swap(tmp);
}
swap()之后,迭代器、引用、指针仍然指向原先所指的位置,但是都换了指向对象,此时它们都失效。也就是说,swap()后,v和tmp的容器名换了,元素换了,容量换了,但是迭代器、引用、指针的指向没变,原来的v.begin()现置身于tmp容器中。                     

  3.vector 的数据结构 

template<class T, class  Alloc=alloc>

class vector{

........

public://嵌套型别定义

typedef         T                      value_type;

typedef         value_type*      pointer;

typedef         value_type*      iterator;

typedef         value_type&     reference;

typedef         size_t               size_type;

typedef         ptrdiff_t            difference_type;

protected:

iterator  start;

iterator  finish;

iterator  end_of_storage;

public:

iterator begin() {return start;}

iterator end()  {  return end;}

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);}

reference front() {return *begin();}

reference back() {return *(end()-1);}

........

}

4.vector的push_back、pop_back、erase、clear、insert的实现内容:

1.push_back()

以push_back()向vector尾端添加元素,首先检查是否还有备用空间,如果有,直接在备用空间添加,调整迭代器。如果没有备用空间,就扩充空间(重新配置、移动数据、释放原空间)。

void push_back(const T& x){

if(finish!=end_of_storage){   //还有备用空间

construct(finish,x);

++finish;

}

else {    //无备用空间

<
4000
span style="font-size:14px;">insert_aut(end(),x);

}

template <class T,class Alloc>

void  vector<T,Alloc>::insert_aut(iterator position, const T& x){

if(finish!=end_of_storage){

construct(finish,*(finish-1));

++finish;

T x_copy=x;

copy_backward(position,finish-2,finish-1);

*position=x_copy;

}else{

const  size_type  old_size=size();

const  size_type  len=old_size!=0? 2*old_size:1;  //分配原来空间的2倍,前半段放原数据,后半段放新数据

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(new_start,new_finish);

data_allocator::deallocate(new_start,len);

throw;

}

destroy(begin(),end());

deallocate();

start=new_start;

finish=new_finish;

end_of_storagenew_start+len;

}

}

2.pop_back()

void pop_back(){

--finish;

destroy(finish);

}

3.erase()

iterator erase(iterator first,iterator last){    //清除[first,last)中的元素

iterator i=copy(last,finish,first);

destroy(i,finish);

finish=finish-(last-first);

return first;

}

iterator  erase(iterator position){   //清除某个位置上的元素

if(position!=end()-1)

  copy(position+1,finish,position);

--finish;

return position;

}

4.insert()

template<class T,class Alloc>
void vector<T,Alloc>::insert(iterator position,size_type n,const T&x){  //插入n个元素,初值为x
if(n!=0){
  if(size_type(end_of_storage-finish)>=n)  { //备用空间大于等于新增元素个数
T x_copy=x;
const size_type  elems_after=finish-position;
iterator old_finish=finish;
     if(elems_after>n){
    uninitialized_copy(finish-n,finish,finish);
    finish+=n;
    copy_backward(position,old_finish-n,old_finish);
    fill(position,position+n,x_copy);
    }
     else{
    uninitialized_fill_n(finish,n-elens_after,x_copy);
    finish+=n-elems_after;
    uninitialized_copy(position,old_finish,finish);
    finish+=elems_after;
    fill(position,old_positin,x_copy);
     }
else{
const size_type old_size=size();
const  size_type  len=old_size_max(old_size,n);
iterator new_start=data_Tallocator::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 _STL_USE_EXCEPTIONS

destroy(begin(),end());

deallocate();

start=new_start;

finish=new_finish;

end_of_storagenew_start+len;

}

}
}
}

end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ STL vector 源码分析