vector为动态数组,与array不同,array是静态空间,一旦配置了就不能改变。而vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。因此,vector的运用对于内存的合理利用与运用的灵活性有很大帮助,我们再也不必因为害怕空间不足而一开始就要求一个很大的array,我们可以使用vector。
stl_vector.h: http://www.sgi.com/tech/stl/stl_vector.h
vector所采用的结构非常简单:连续线性空间。它以两个迭代器start和finish分别指向配置得来的连续空间中目前已被使用的范围,end_of_storage指向整块连续空间(含备用空间)的尾端。
运用这三个迭代器可以轻易得到首尾标志,大小,容量,空容器判断、注标([])运算子、最前端元素值,最后端元素值。这个可以具体看代码。
当增加新元素时,如果超过当时的容量,则容量会扩充至两倍。如果两倍容量扔不足,就扩张至足够大的容量。
1、constructor
vector提供多种constructors:
vector()
vector(size_type n,const T& value)
vector(int n,const T& value)
2、push_back
将新元素插入于vector尾端,要先检查是否有备用空间,如果有就直接在备用空间上构造元素,并调整迭代器finish,使vector变大。如果没有空间了,就扩充空间(重新配置,移动数据,释放原空间)
注意,并不是在原空间之后连续接新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原大小的两倍另外配置一块较大的空间。因此对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了。
前三个都比较容易,直接看代码即可
现在讲一下insert的实现
1、备用空间>=新增元素个数
(1)插入点之后的现有元素个数>新增元素个数
uninitialized_copy(finish-n,finish,finish); //把finsh-n到finish的元素复制到finish之后 finish+=n; //将vector尾端标记后移 copy_backward(position,old_finish-n,old_finish); //把position到old_finish-n的元素复制到old_finsih之后 fill(position,position+n,x_copy); //从插入点开始填入新值
(2)插入点之后的现有元素个数<=新增元素个数
uninitialized_fill_n(finish,n-elems_after,x_copy); //elems_after为position到finish的元素个数 finish+=n-elems_after; //将vector尾端标记后移 uninitialized_copy(position,old_finish,finish); //把finsh-n到finish的元素复制到finish之后 finish+=elems_after; fill(position,old_finish,x_copy); //从插入点开始填入新值
2、备用空间<新增元素个数
const size_type old_size=size(); const size_type len=old_size+max(old_size,n); //决定新长度 iterator new_start=data_allocator::allocate(len); iterator new_finish=new_start; new_finish=uninitialized_copy(start,position,new_start); //首先将旧vector的插入点之前的元素复制到新空间 new_finish=uninitialized_fill_n(new_finish,n,x); //再将新增元素(初值皆为n)填入新空间 new_finish=uninitialized_copy(position,finish,new_start); //最后将旧vector的插入点之后的元素复制到新空间