讨论标准模板库std::vector的容量/大小及其内存增量

原创 2009年07月09日 12:44:00

首先解释一下容量/大小的区别:
  std::vector::capacity() : 指容器的能容纳多少个。
  std::vector::size() : 指容器当前已装多少个。
明白上面的意思思路就清晰多了。

 

这几天有同事用vector的时候遇到问题,说是当push_back以后,以前引用了vector的地址就不能访问。
造成以前引用的地址不能使用的原因估计大家都知道。
主要原因是vector有一个内存增量机制。


内增量机制是:为了满路容器的连续内存访问,当vector发现自己内存不够用,就需要重新申请内存,
然后复制旧的数据过去,删除旧的数据,重新指向新的数据地址。
当这个复制过程一结束的时候,以前引用了下标为0的vector内存地址就会不再是该数据地址了,
已被复制走的原有数据已删除成为野内存。
这时需要重去引用一次。

 

关于这个增量机制网上有多种说法,
  1说法:按原有尺寸的2倍增长,即:new_capacity = capacity_size * 2;
  2说法:按原有尺寸的50%增加,即:new_capacity = capacity_size / 2 + capacity_size;
  3说法:按数据尺寸倍数增长,即 sizeof(class) * 2;
  4说法:按字节来,即: (1024)/sizeof(class);


就此问题,我专门去看了看vector的原代码。得到的结果是:2说法正确。
这点可以从std::vector::_Insert_n(iterator, size_type, const _Ty&)的原代码中可以看出:

// 如果容量 < 大小 + 新数量增量
else if (_Capacity < size() + _Count)
{
  // 容量 = 容量 + 容量 / 2;
  _Capacity = max_size() - _Capacity / 2 < _Capacity ? 0 : _Capacity + _Capacity / 2; 
  // 容量 < 大小 + 新增数量
  if (_Capacity < size() + _Count)
    // 容量 = 大小 + 新增数量
    _Capacity = size() + _Count;
  // 申请新内存
  pointer _Newvec = this->_Alval.allocate(_Capacity);
  // 开始引用地址
  pointer _Ptr = _Newvec;
  // 复制与删除过程
  ......
}

 

那么如何解决我即想引用vector的地址又不需要经常去刷新该地址呢?
同时又解决掉vector的复制问题,也解决掉有些类的复制构造?
方法还是有的。
这里就有前面提到的容量/大小的因素了。
容量必然大于大小,是肯定的,即:capacity >= size;

 

方法1:
  创建std::vector容器,并调用std::vector::reserve(int n);
  告诉vector的直接增加n个数据并分配内存,
  这样的话push_back数量在n以内,引用的地址不会发生变化。vector内存也没有改变
  但如果事先告诉n的程序,这种方法是最好的。
  例:
    std::vector< int > vA;
    vA.reserve(10);
    vA.push_back(7);
    vA.push_back(6);
    vA.push_back(2);
    vA.push_back(9);
    int* pAddress = &vA[0];


方法2:
  通过构造函数告诉该容量容量
  各种带参数构造类似,这里不多举例
  例:
    std::vector< int > vA(10);
    int* pAddress = &vA[0];
    pAddress[0] = 7; // 等于 vA[0] = 7;
    pAddress[1] = 6; // 等于 vA[1] = 6;
    pAddress[2] = 2; // 等于 vA[2] = 2;
    pAddress[3] = 9; // 等于 vA[3] = 9;


方法3:
  与方法1方法一样。只是调用函数是:std::vector::resize(int n);

 

再说说resize与reserve的区别
resize:新的大小 < 现有大小,会删除多余的部分
        新的大小 > 现有大小,会在现有尺部插入新的数据,这时就有可能造成容量变化
        其它情况不操作。
reserve:当前容量 < 传入容量,会根据新的容量创建内存,并复制。
         当前容量 > 传入容量,不理踩
         其它情况不操作。

vector大小与容量的关系

vector优异性能的秘诀之一,就是配置比其所容纳的元素所需更多的内存。 vector中的函数capacity()返回vector实际能够容纳的元素数量,如果超出这个数量,vector就会重新配...
  • zhuozhibin
  • zhuozhibin
  • 2015年01月25日 15:07
  • 2213

c++积累(4):vector对象初始化和大小、容量

#include #include #include using namespace std; int main() { vectormyVector; myVector.reserve...
  • laohu_tiger
  • laohu_tiger
  • 2014年06月16日 12:58
  • 2746

STL之vector的使用一(初始化vector)

简介:vector可用于代替C中的数组,或者MFC中的CArray,从许多说明文档或者网上评论,一般一致认为应该多用vector,因为它的效率更高,而且具备很好的异常安全性。而且vector是STL推...
  • a237653639
  • a237653639
  • 2014年03月24日 23:15
  • 4133

ArrayList和Vector区别以及其扩容机制

ArrayList和Vector区别以及其扩容机制 相同点:   1、ArrayList和Vector都是继承了相同的父类和实现了相同的接口     (extends AbstractList im...
  • dietime1943
  • dietime1943
  • 2017年01月09日 15:40
  • 896

ACM学习历程7——Vector向量容量扩展机制

Vector向量容器相当于一个动态的数组,当向向量容器中不断加入元素,若超过容器本身的大小限制,vector会自动拓展大小,在这过程中涉及到内存的分配和回收。在vector中有size()和capac...
  • u010480899
  • u010480899
  • 2016年08月23日 16:14
  • 1282

C++vector容器大小增长规律的总结

问:“vector大小是如何增长的?” 答:“自动增长的” 问:“增长规律是怎么?” 答: 。。。。。。 那么, 今天就来探究一下vector容器的大小增长规律:vector中得到大小的的函...
  • thinkerleo1997
  • thinkerleo1997
  • 2017年07月17日 16:20
  • 1436

关于vector大小(size)和容量(capacity)总结

主要介绍了vector 容器大小相关的操作函数(size、max_szie、capacity),同时介绍了容器大小超出容器capacity能力会内存重新分配以及iterator失效简单分析。同时给出了...
  • xiao3404
  • xiao3404
  • 2016年04月08日 22:37
  • 16897

vector内存增长方式

vector可以理解为动态数组,既然是数组,那么它在内存中就应该是一块连续的内存,但vector是如何支持动态增长的呢?...
  • qq_26849233
  • qq_26849233
  • 2017年04月25日 13:53
  • 1489

STL中vector的内存分配机制

一些好的公司校园招聘过程中(包括笔试、面试环节),经常会涉及到STL中vector的使用(主要是笔试)及其性能(面试)的分析。今天看了下相关文章,也写了几个小的测试程序跑了跑。算是总结下,希望对需要的...
  • u010497938
  • u010497938
  • 2015年08月25日 22:44
  • 2189

c++ vector的容量增长方式

以前一直以为vector的capacity的增长方式是翻倍增长的,但是实验了一下,并不是所想的那样 *2增长。当然也是按照一定的规律去增长,具体是什么规律,不同的编译器应该有不同的实现吧。 ...
  • soloopin
  • soloopin
  • 2012年11月27日 17:32
  • 5425
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:讨论标准模板库std::vector的容量/大小及其内存增量
举报原因:
原因补充:

(最多只允许输入30个字)