C++ STL容器之vector的知识点及源码分析
2017-10-18 14:51
435 查看
vector的数据安排和array非常相似,array是静态空间,一旦配置就不能改变,如果要改变的话,首先要配置新的空间,把元素移过去,释放原来的空间。而vector模塑出个一dynamic array,随着元素加入,它的内部机制自行扩充空间(一旦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() //销毁所有元素,释放内存
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容器中。
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);}
........
}
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;
}
}
--finish;
destroy(finish);
}
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;
}
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
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
相关文章推荐
- STL源码分析之vector容器
- 由C++ STL的vector容器中存储的对象拷贝引起的对capacity属性 的理解
- Vector源码分析
- 深入理解 spring 容器,源码分析加载过程
- Vector源码分析
- 几种常见 容器 比较和分析 hashmap, map, vector, list ...hash table
- OpenCV2.4.9源码分析——Support Vector Machines
- Spring IOC 容器源码分析 - 余下的初始化工作
- boost::mpl::vector(MSVC)源码分析
- 给jdk写注释系列之jdk1.6容器(10)-Stack&Vector源码解析
- Java数据结构源码分析-Vector
- caffe源码分析 vector<Blob<Dtype>*>& bottom
- 一 spring源码分析--- IOC容器
- 四 spring 源码分析--- 容器启动 时序图
- spring 源码分析及知识点总结
- Hadoop源码分析12: IPC流程(7)容器
- Hadoop源码分析26 JobTracker主要容器和线程
- Spring IOC 容器源码分析
- 开始我的第一篇文章 vector容器的源码解析
- java util包学习(5) Vector 源码分析