STL序列容器之vector

1、基本概念

  我们都知道c++原生的array是静态空间,一旦分配就不可更改,如果想要扩展大小就必须自行处理。vertor在提供array功能的基础上,帮我们完成空间的扩展,让我们使用起来更加的自由。

2、迭代器

  vector提供的迭代器具备基本的算术运算,可随机访问vector内部的元素,因而属于随机迭代器。

3、容量扩展

  当vector内部的空间已经使用完后,此时再向其中添加元素时,就需要扩展vector的容量。扩展容量时,需要进行以下三个步骤:
1. 分配一块新的内存,使其能够容纳包括新添加的元素在内的所有元素;
2. 将旧内存中的元素拷贝到新的内存中;
3. 将新添加的元素添加到新内存中;
4. 释放就内存。
  由此可以看到,vector对空间进行扩展的代价是十分高的,如果我们每次扩展的时候容量只增加1,那么当vector使用空间已满后,每添加一个元素,就会引起一次容量扩展,这显示是不可接受的。STL标准设定的vector容量扩展系数为2,即每次扩展时,新的容量大小为当前容量大小的两倍。我们通过下面的测试代码进行验证一下:

vector<int> a;
a.push_back(1);
cout<<"size:"<<a.size()<<endl; //size:1
cout<<"capacity:"<<a.capacity()<<endl; //capacity:1
a.push_back(2);
cout<<"size:"<<a.size()<<endl; //size:2
cout<<"capacity:"<<a.capacity()<<endl; //capacity:2
a.push_back(3);
cout<<"size:"<<a.size()<<endl; //size:3
cout<<"capacity:"<<a.capacity()<<endl; //capacity:3
a.push_back(4);
cout<<"size:"<<a.size()<<endl; //size:4
cout<<"capacity:"<<a.capacity()<<endl; //capacity:4
a.push_back(5);
cout<<"size:"<<a.size()<<endl; //size:5
cout<<"capacity:"<<a.capacity()<<endl; //capacity:6
a.push_back(6);
cout<<"size:"<<a.size()<<endl; //size:6
cout<<"capacity:"<<a.capacity()<<endl; //capacity:6

  通过上面的测试代码,你们一定很奇怪,根据log显示,容量的增长并不是按照两倍的速率进行。这里要说明的是STL是有多个实现版本的,不同版本的实现是不尽相同的,我测试使用的是vs2012,下面可以看下实现源码:

size_type _Grow_to(size_type _Count) const
{   
    // grow by 50% or at least to _Count
    size_type _Capacity = capacity();

    _Capacity = max_size() - _Capacity / 2 < _Capacity
        ? 0 : _Capacity + _Capacity / 2;    // try to grow by 50%
    if (_Capacity < _Count)
        _Capacity = _Count;
    return (_Capacity);
}

  通过上面的代码,我们可以看到该版本的容量增长系数设定为1.5,而不是标准的2。这里知乎上的大神也有讨论过系数设定为多少才是最优的,我暂时还没弄懂,也不做讨论。但由此我们知道一点,当我们测试的结果跟一些教程的结果不一致时,先看看是不是STL的版本不同造成的。

4、内存释放

  vector有提供自己的清理函数,但实际的内存是否真的释放了,需要先测试一下。看下下面的代码:

vector<int> a;
a.push_back(1);
cout<<"size:"<<a.size()<<endl; //size:1
cout<<"capacity:"<<a.capacity()<<endl; //capacity:1
a.push_back(2);
cout<<"size:"<<a.size()<<endl; //size:2
cout<<"capacity:"<<a.capacity()<<endl; //capacity:2
a.push_back(3);
cout<<"size:"<<a.size()<<endl; //size:3
cout<<"capacity:"<<a.capacity()<<endl; //capacity:3
a.push_back(4);
cout<<"size:"<<a.size()<<endl; //size:4
cout<<"capacity:"<<a.capacity()<<endl; //capacity:4
a.push_back(5);
cout<<"size:"<<a.size()<<endl; //size:5
cout<<"capacity:"<<a.capacity()<<endl; //capacity:6
a.push_back(6);
cout<<"size:"<<a.size()<<endl; //size:6
cout<<"capacity:"<<a.capacity()<<endl; //capacity:6
a.clear();
cout<<"size:"<<a.size()<<endl; //size:0
cout<<"capacity:"<<a.capacity()<<endl; //capacity:6

  这里我们调用的clear函数,可以看到size为0,可容量还是6,证明内存并没有被释放,只是设定为未使用。如果想要真正释放内存,可以使用下面的方法:

vector<int>().swap(a);
cout<<"size:"<<a.size()<<endl; //size:0
cout<<"capacity:"<<a.capacity()<<endl; //capacity:0

  这里我们使用一个空vector临时变量与a进行交换,导致a的容量变为0,而临时变量获取了a的内存,在作用域结束后就被系统回收了,从而间接达到释放a所使用的内存的目的。

5、特殊情况

  vector是一个模板类,理论上是可以设定vector,但是vector涉及一下两个问题:
1. vector并不是一个容器;
2. vector并不保存bool类型的值,而是使用bit以节省空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值