讨论标准模板库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:当前容量 < 传入容量,会根据新的容量创建内存,并复制。
         当前容量 > 传入容量,不理踩
         其它情况不操作。

相关文章推荐

(转)标准模板库(STL)的 std::string 与Unicode的使用

是的,一旦知道 TCHAR 和_T 是如何工作的,那么这个问题很简单。基本思想是 TCHAR 要么是char,要么是 wchar_t,这取决于 _UNICODE 的值: // abridged f...
  • gxj1680
  • gxj1680
  • 2011年05月05日 17:40
  • 682

C++的标准模板库STL中实现的数据结构之链表std::list的分析与使用

摘要 本文主要借助对C++的标准模板库STL中实现的数据结构的学习和使用来加深对数据结构的理解,即联系数据结构的理论分析和具体的应用实现(STL),本文是系列总结的第二篇,主要针对线性表中的链表 S...

标准模板库(STL)学习探究之vector容器

标准模板库(STL)学习探究之vector容器  C++ Vectors    vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。vecto...

【C++】 C++标准模板库(一) Vector

一:C++ VectorsVectors 包含着一系列连续存储的元素,其行为和数组类似。访问Vector中的任意元素或从末尾添加元素都可以在常量级时间复杂度内完成,而查找特定值的元素所处的位置或是在V...

标准模板库之vector示例代码

  • 2015年06月25日 16:24
  • 2KB
  • 下载

[C++标准模板库:自修教程与参考手册]关于vector

什么是vector可以这样认为,vector就是一个动态的数组,其中的元素必须具备assignable(可赋值)和copyable(可拷贝)两个性质。 vector的一些重要的性质 vector支持...

C++入门学习——标准模板库之vector

vector(向量容器),是 C++ 中十分有用一个容器。vector 之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector 是一个能够存放任意类型的动态数组,能够...

C++的标准模板库STL中实现的数据结构之顺序表vector的分析与使用

一、摘要 本文主要借助对C++的标准模板库STL中实现的数据结构的学习和使用来加深对数据结构的理解,即联系数据结构的理论分析和具体的应用实现(STL),本文是系列总结的第一篇,主要针对线性表中的顺序表...

标准模板库STL中vector使用参考手册

简介:   vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。   为了可以使用vector...

标准模板库STL详解之vector

泛型是标准模板库(STL)的核心思想,常用STL组件主要有算法,函数对象,容器和迭代器。STL泛型算法具有相似的操作接口。借助于迭代器,程序能够以方便统一的形式访问不同的数据类型,不同存储形式的元素。...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:讨论标准模板库std::vector的容量/大小及其内存增量
举报原因:
原因补充:

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