一、什么是序列式容器
所谓序列容器,即以线性排列(类似普通数组的存储方式)来存储某一指定类型(例如 int、double 等)的数据,需要特殊说明的是,该类容器并不会自动对存储的元素按照值的大小进行排序。
需要注意的是,序列容器只是一类容器的统称,并不指具体的某个容器,序列容器大致包含以下几类容器:
array<T,N>,vector<T>,deque<T>,list<T>,forward_list<T>
二、vector原理
结构
源码
/*
vector与array数组比较类似 但是array是静态空间,一旦配置了空间就不能够再改变
vecotr是动态空间,随着元素的加入,它的内部机制就会自行扩充空间来容纳新的元素
//下面将真是vector函数的具体实现
//vector是一个连续的线性空间
*/
//alloc是SGI的空间配置器
template <class T,Alloc=alloc>
class vector{
public:
//vector的嵌套型别定义
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:
//以下,simple_alloc是SGI 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 deallocate(){
if(start)//如果它不是空的
data_allocator(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 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);}
vector():start(0),finish(0),end_of_storage(0){}
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(){
destory(start,finish);//全局函数,见allocate小节
deallocate();//这是vector的一个member function
}
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
insert_aux(end(),x);//vevtor的成员函数
}
void pop_back(){//将最尾端的元素取出来
--finish;
destroy(finish);//全局函数
}
iterator erase(iterator position){//清除某个位置上的元素
if(position+1!=end())
copy(position+1,finish,position);//后续元素向前移动
--finish;
destory(finish);//全局函数
return position;
}
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());}
void clear(){erase(begin(),end());}
protected:
//配置空间并填满内容
iterator allocate_and_fill(size_type n,const T&x){
iterator result=data_allocator::allocate(n);
uninitialized_fill_n(result,n,x);//全局函数
return result;
}
}
};
由源码,可以清晰的看到earse,resize,clear,push_back等函数的结构
三、vector申请内存
注意,所谓的动态增加大小,并不是在原空间之后接续新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原大小的两倍另外配置一块较大空间,然后将原内容拷贝过来,然后才开始在原内容之后构造新元素,并释放原空间。因对 vector的任何操作,一旦引起空间重新配置,指向原 vector的所有迭代器就都失效了。这是程序员易犯的一个错误,务需小心。
下面我们来看一下是如何vector重新申请内存的
1.如果当前可使用的容量小于要插入的数量,那么就需要重新申请内存
2.如果最大容量减去当前容量小于1,那么抛出vector过长异常
3.申请内存之前,容量需要按照增长50%或为插入的数量
4.申请新内存,将原始空间析构函数释放,重新计算头尾指针的偏移量
实例
vector <int> wgw;
cout << "initilize size is: " << wgw.size() << endl;
cout << "initilize capacity is :" << wgw.capacity() << endl;
wgw.resize(10,2);
cout << "wgw size is: " << wgw.size() << endl;
cout << "wgw capacity is :" << wgw.capacity() << endl;
wgw.resize(3,10);
cout << "wgw size is :" << wgw.size() << endl;
cout << "wgw1capacity is:" << wgw.capacity() << endl;
for (auto &row : wgw) {
std::cout <<row <<std::endl;
}
参考:
http://c.biancheng.net/view/409.html
https://blog.csdn.net/Zyong139064359/article/details/91391865
https://www.jianshu.com/p/e0b59a4a8b51