为了支持随机访问,vector容器中的元素是连续存储的。再向vector中插入元素时,如果vector当前的空间已经满了,没有额外的空间存储新元素时,vector会申请一块更大的空间,将所有元素拷贝到新空间中,并将待插入的元素插入到新空间里。那么vector在当前空间已满的情况下重新申请空间时,究竟会申请多大的空间?
当然vector不会每次重新申请的空间只比原有空间多出一个元素的大小,因为如果采用这种策略,意味着每插入一个元素,vector都处于已满的状态,只要在vector中再插入一个新元素,都要重新申请空间,这样无疑效率很低。
另外,vector也不会在元素很少的情况下申请一块巨大的空间,因为这样会造成不必要的空间浪费。如果一个拥有上万个元素空间的vector中只存储了一两个元素,那么剩余的空间暂时都会处于空闲状态。
vector容器在堆空间中建立了一个一维数组,地址空间是连续的,支持快速随机访问。 但是在vector中插入删除元素的效率较低,插入操作会导致插入位置及其后面的元素向后移动,删除元素会导致删除位置之后的元素向前移动。在vector尾部插入删除元素最快,不需要移动任何元素;在头部插入删除元素最慢,需要移动所有元素。
下面通过代码来看一下实现分配的机制:
#include <iostream> #include <vector> using namespace std; int main() { /* size函数返回容器中已保存元素的个数,capacity函数返回当前容器中最多可以存放的元素个数。 size = capacity 容器已满 剩余空间 = capacity - size (size < capacity) */ vector<int> v(2, 0); //定义一个大小为2的容器,并将容器中两个元素初始化为0 cout << "size = " << v.size() << " \tcapacity = " << v.capacity() << endl; //size = capacity = 2 //通过循环向容器中添加8个元素 for (int a = 1; a <= 8; a++) { v.push_back(a); cout << "size = " << v.size() << " \tcapacity = " << v.capacity() << endl; } return 0; }可以看到,第一次分配了2个空间,第二次分配了4个空间,第三次分配了8个空间…,所以可以看到,vector每次申请空间的大小都是上一次分配的2倍。
从上面的分析中可以看出,前两次都只分配了1个空间,第三次分配了2个空间,第四次分配了3个空间,第五次分配了4个空间。
所以,当分配次数多了以后,vector申请的空间要比实际需要的空间适当大一些,这样做的好处是不必在每次插入元素时都重新分配空间,也不会过分的浪费空间。大多数时候vector中都会有适量的剩余空间,只有当剩余空间用尽,vector才会申请一块更大的空间,重新申请的空间除了能装下所有的旧元素和待插入的新元素外,还有一部分预留空间供今后插入元素使用。
至于每次具体申请多大的空间,不同版本可能采用不同的策略。有些资料中提出每次申请的空间都是上次申请空间的两倍,实际上是不严谨的,因为这种策略可能在某个版本中得到验证,但在其他版本中就不灵了。
可以验证,当插入100个数时,capacity的取值依次为2->3->4->6->9->13->19->28->42->63->94->141->…,差值为1->1->2->3->4->6->9->14->21->31->47->…
