1、vector定义及概述
vector与array非常相似,唯一的区别在于灵活性,数组是静态空间,一旦定义就不能改变,变大变小都需要客户端自己重新配置新的空间,然后将元素从旧址搬到新址,再把原来的空间还给系统。
vector是动态空间,随着元素的加入,他的内部机制会自行扩充空间以容纳新元素。
1.vector的底层实现
vector所采用的是一个连续的线性空间,以两个迭代器start和finish分别指向连续空间中已被使用的空间的头和尾,以迭代器end_of_storage指向整个连续空间的尾部(包括备用空间)。
template <class T, class Alloc = alloc> //vector默认使用alloca作为空间配置器
class vector {
···
protected:
iterator start; // 表示目前使用空间的头
iterator finish; // 表示目前使用空间的尾
iterator end_of_storage; // 表示目前可用空间的尾
...
}
为了降低空间配置时的速度成本,vector实际配置的大小通常比客户端的需求更大一些,以便将来可能的扩充。
2.vector的初始化
vector<T> v1 // 默认初始化, 此时v1为空。
vector<T> v1(v2) // 执行的copy初始化,此时v1与v2的内容相同
vector<T> v1 = v2 // 与上面相同,都会执行copy构造函数
vector<T> v1(n) // 此时v1的size大小为n ,它里面的值是根据T的类型进行默认初始化的
vector<T> v1(n, a) // v1的初始化为n个值为a的元素
vector<T> v1{a, b, c} // 列表初始化,v1内现在的元素就是a, b, c
vector<T> v1 = {a, b, c} // 列表初始化,v1内现在的元素就是a, b, c
3.vector的常用操作
temple <class T,class Alloc=alloc>
class vector
{
public:
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();} //判断容器是否为空
reference operator[](size_type n)
{return *(begin()+n);}
reference front(){return *begin();} //返回头部元素的引用
reference back(){return *(end()-1); //返回尾部元素的引用
}
除了上面说到的begin和end之外,还有rbegin和rend
v.rbegin()返回的是一个指向容器的最后一个元素逆序迭代器
v.end()返回的是一个指向容器中第一个元素的上一个位置的逆序迭代器
查看容器大小的操作还有max_size()和resize()
v.max_size()返回容器中可容纳最多的元素个数
v.resize(n) 调整容器v的长度大小,使其能容纳n个元素,若n<v.size(),则删除多出来的长度
v.resize(n,t) 调整容器v的大小,使其能容纳n个元素,所有新添的元素值初始化为t
4.vector的插入和删除
v.push_back(t)//在容器尾部插入一个元素t,时间复杂度为O(1)
void push_back(const T& x)
{
if(finish!=end_of_storage-begin)//判断是否还有备用空间
{
construct(finish,x); //直接在备用空间中插入元素
++finish; //调整尾部位置
}
else //没有备用空间则扩容
{
insert_aux(end(),x);
}
}
v.insert(p,x)//在迭代器p所指向的元素前插入新元素x,返回指向新元素的迭代器
iterator insert(iterator position,const T& x)
{
size_type n=position-begin();
if(finish!=end_of_storage-begin&&position==end())
{
construct(finish,x);
++finish;
}
else
{
insert_aux(position,x);
return begin()+n;
}
}
v.insert(p,n,x)//在迭代器p所指向的元素前插入n个初始化为x的元素
void insert(iterator pos,int n,const T& x)
{
insert(pos,(size_type)n,x);
}
v.insert(p,f,l)//在迭代器p所指向的元素前插入f和l之间的元素
temple <class InputIterator>
void insert(iterator position, InputIterator first, InputIterator last)
{
range_insert(position, first, last, iterator_category(first));
}
v.erase(p)//删除迭代器p指向的元素,返回一个指向被删除元素后面的元素,
如果配置项容器的最后一个元素,则返回的迭代器指向超出末端的下一个位置,
如果p本身就是超出容器末端的下一个位置,则该函数未定义
iterator erase(iterator position)
{
if(position+1!=end())
copy(position+1,finish,position);
--finish;
destroy(finish);
return position;
}
v.erase(f,l)//删除f到l之间的所有元素,返回一个迭代器,它指向被删除元素段后面的元素。
如果l本身就是指向超出容器末端的下一个位置,
则返回的迭代器也指向容器末端的下一个位置
iterator erase(iterator f,iterator l)
{
iterator i=copy(l,finish,f);
destroy(i,finish);
finish=finish-(l-f);
return f;
}
v.clear()//删除容器中能够所有元素
{
erase(begin(),end());
}
v.pop_back()//删除容器中的最后一个元素
void pop_back()
{
--finish;//将尾端标记往前移一格
destroy(finish);
}
2.vector的扩容机制
- 倍数开辟更大的内存
- 旧的数据拷贝到新的内存
- 释放旧内存,指向新内存
3.vector的优缺点
-
优点:支持快速的尾部插入和删除
-
缺点:任意位置插入和删除的时间复杂度高