vector和array的数据安排和操作方式比较相似, 但是二者又有区别,区别就在于空间运用的灵活性
array是静态空间,配置之后就不能更改,只能重新配置新的空间;
vector是动态空间,加入元素时其内部会自行扩充空间区容纳新元素;vector不存在浪费内存和越界问题,随机访问比较快,但是头部插入和删除比较慢(要进行移动),尾部插入和删除较快;
vector的迭代器类型:Rabdom Access Iterator(随机存取迭代器),vector支持随机存取,普通指针又有此能力,所以用的是普通指针。
vector的应用场景:vector支持随机存取,动态扩张,适合多查询的应用场景,但是,其内存需要保持连续,所以在删除某个元素后,其后续元素需要前移,这样会带来消耗,所以不适合随机删除的场景。
vector实现技术的关键是其对大小的控制以及重新配置时的数据移动效率
vector的数据结构:
vector采用的是数据结构是线性连续空间。用两个迭代器start和finish来指向配置空间中已经使用的空间的头和尾,finish - start的结果就是当前已经使用的空间的大小; 用迭代器end_of_storage表示所配置空间的尾部;则end_of_storahe - finish就是剩余的空间大小, end_of_storage - start就是整块空间的大小;
注意finish指向的是已使用空间的最后一个元素的下一个空间,在得到尾元素的引用时要将迭代器 - 1;
template<class T, class Alloc = alloc>
class vector
{
...
protected:
iterator start;
iterator finish;
iterator end_of_storage;
...
};
vector使用alloc作为空间配置器,vector还定义了一个data_allocator配置器,目的是为了更方便的以元素大小为单位来配置空间;
vector的空间配置策略:
当利用push_back()在vector尾部插入元素时,push_back()函数
(1)先检查vector是否还有备用空间,如果有就直接在备用空间构造元素,并调整迭代器finish,使得vector变大;
(2)如果没有空间就扩充空间(重新配置空间, 移动数据, 释放原有空间)
void push_back(const T& x)
{
if(finish != end_of_storage){
//还有备用空间
construct(finish, x); //内部采用定位new实现
++finish;
}else{
//已经没有备用空间
insert_aux(end(), x);
}
}
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{
const size_type old_size = size();
const size_type len = old_size != 0 ? 2 * old_size : 1;
//若原大小为0,则配置一个元素大小
//若原大小不为0,则配置原大小的两倍; 前半段用来存放原数据,后半段用来存放新数据
iterator new_start = data_allocator::allocate(len); //配置空间
iterator new_finish = new_start; //新配置的空间其内还没有元素,所以迭代器的头尾指向相同
new_finish = uninitialized_copy(start, position, new_start); //将原数据至插入点的元素拷贝至新的vector
construct(new_finish, x); //将x插入
++new_finish; //调整迭代器
new_finish = uninitialized_copy(position, finish, new_finish); //将原vector中的插入点至finish的元素拷贝至新vector
//释放原vector
destroy(begin(), end()); //释放原vector中的元素
deallocate(); //释放原vector空间
//调整迭代器,指向新的vector
start = new_start;
finis = new_finish;
end_of_storage = new_start + len;
}
}
vector的插入操作
template<class T, class Alloc>
void vector<T, Alloc>::insert(iterator position, size_type n, const T& x)
{
if(n != 0){ //插入元素个数不为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){ //插入点后的现有元素个数>n
//将finish前的n个元素后移至finish后
uninitialized_copy(finish - n, finish, finish);
finish += n; //调整迭代器(后移)
//将插入点至finish-n之间的元素后移至旧finish之前
copy_backward(position, old_finish - n, old_finish);
//将新元素插入至position至position+n之间的位置
fill(position, position + n, x_copy);
}else{ //插入点后的元素个数<= n
//先在finish后插入n - elems_after(finish前可插入的元素的剩余个数)个元素
uninitialized_fill_n(finish, n - elems_after, x_copy);
finish += n - elems_after; //调整迭代器
//再将插入点至旧的finish之间的元素后移至新的finish后
uninitialized_copy(position, old_finish, finish);
finish += elems_after; //调整迭代器
//最后将x_copy插入position至旧的finish之间的位置
fill(position, old_finish, x_copy);
}
}else{ //备用空间的元素个数<= n
//(1) 确定新的空间长度,旧长度的两倍或者是旧长度+新曾的元素个数
const size_type old_size = size(); //得到旧的长度
const size_type len = old_size + max(old_size, n); //确定新的长度
//(2 )配置新的vector空间
iterator new_start = data_allocator::allocate(len);
iterator new_finish = new_start;
//(3) 将旧vector的插入点之前的元素插入(复制到)新的vector空间
new_finish = uninitialized_copy(start, position, new_start);
//(4) 将新增的元素插入new_finish后
new_finish = uninitialized_fill_n(new_finish, n, x);
//(5) 将旧vector空间的position后至finish间的元素插入新的vector的new_finish后的空间
new_finish = uninitialized_copy(position, finish, new_finish);
//(6) 清除旧的元素并释放旧vector的空间
destroy(start, finish);
deallocate();
//(7) 调整新的迭代器标记
start = new_start;
finish = new_finish;
end_of_storage = new_start + len;
}
}
}
vector的删除操作:
//尾部删除
void pop_back()
{
--finish;
destroy(finish);
}
//删除某个位置上的元素
iterator erase(iterator position)
{
if(position + 1 != end()){
//copy从前向后拷贝,即*position = *(position + 1),直到拷贝至finish - 1位置结束,返回一个迭代器position + (finish - (position + 1))
copy(position + 1, finish, position);
}
--finish; //调整迭代器
destroy(finish); //释放最后一个元素
return position; //返回要删除的位置
}
//删除某个范围内的元素
iterator erase(iterator first, iterator last)
{
//将last后的所有元素前移,返回一个first + (finish - last)的迭代器
iterator i = copy(last, finish, first);
destroy(i, finish); //释放c从i至finish之间的所有元素
finish = finish - (last - first); //调整迭代器
return first; //返回要删除的起始位置
}
调整容器大小的操作
//增加或删除元素使被控序列的长度变为new_size长
void resize(size_type new_size, const T& x) //添加值为x的元素
{
if(new_size < size()){ //缩短被控序列(vector)的长度
erase(begin() + new_size, end()); //删除new_size长度后至end()的元素
}else{ //增加被控序列的长度
insert(end(), new_size - size(), x); //在end()后插入new_size - size()个元素x,使序列长度变为new_size长
}
}
void resize(size_type new_size) //使被控序列的长度变为new_size
{
resize(new_size, T()); //添加值为T()的元素
}
清空容器
//清空vector序列
void clear()
{
erase(begin(), end());
}
vector容器的其他操作
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();
}
referance operator[](size_type n) //重载[],得到第n个元素
{
return *(begin() + n);
}
reference front() //得到首元素的引用
{
return *begin();
}
reference back() //得到末尾元素的引用
{
return *(end() - 1);
}
vector的析构操作
~vector()
{
destroy(start, finish); //删除所有元素
deallocate(); //释放空间
}
//释放vector空间
void deallocate()
{
if(start){
data_allocator::dedallocate(start, end_of_storage - start);
}
}