栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

[C++] vector内存分配与释放机制

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

[C++] vector内存分配与释放机制

vector相关函数
  • size():vector当前拥有的元素个数

  • capacity():vector在必须分配新存储空间之前可以存储元素总数

    创建完vector之后,size和capacity都为0,但是向vector插入元素之后,会发生变化,通常capacity大于等于size,这是vector内存增长机制决定的

  • push_back():向vector最后插入一个元素,在调用push_back时,若当前的capacity已经不能够放入新的元素(capacity=size),那么vector会重新申请一块内存,把之前内存里的元素拷贝到新的内存当中,然后把push_back的元素拷贝到新的内存中,最后要析构原有vector并释放原有内存,所以说这个过程效率是极低的,为了避免频繁的分配内存,C++每次申请内存都会成倍增长

  • reserve(a):vector预留空间a,但是空间内不真正创建对象(capacity=a,size=0),加入元素时,调用push_back或者insert函数,若添加元素没有超出预留,那么不会对内存进行重新分配。若加入的元素个数超过reserve的值,就会触发push_back的空间预留机制

  • resize(a, 0):改变vector的大小,创建对象(指定或默认为0,初始capacity=size=a),此时再调用push_back函数,新元素是加在新的空间后面,同样也会触发push_back的空间预留机制

    vector类型提供resize操作来改变vector所包含的元素个数:如果当前vector长度大于新的长度值,则该vector后部的元素会被删除;如果当前vector长度小于新的长度值,则系统会在该vector后部添加新元素

    reserve()和resize()的区别:

    • reserve函数只有一个参数,即需要预留的空间;resize函数可以有两个参数,第一个参数是vector新的大小,第二个参数是要加入vector中的新元素,如果第二个参数省略,那么调用元素对象的默认构造函数
    • 当不超过预留空间时,reserve不涉及内存重新分配,resize会涉及内存重新分配。但是如果是对空vector的操作,二者看不出区别
    • reserve函数只修改capacity大小,不修改size大小
    • resize函数既修改capacity大小,也修改size大小
  • clear(a):清空vector中的元素,vector所占用的内存空间依然存在,无法保证内存的回收。一维vector.clear(),清空一维的元素,保留着列的capacity;二维vector.clear(),清空各行的列,并回收列内存,保留行的capacity

  • a.swap(b):将a中的元素和b中的元素进行整体交换

    • 利用swap去除vector多余的容量:vector< T >(x).swap(x);x是当前要操作的vector,T是类型
    • 利用swap清空vector容器:vector< T >().swap(x)
vector内存增长的方式和特点
  • vector容器的capacity可以增加,不可以减少

    当使用push_back、insert、emplace等成员函数的时候,可能会增加capacity;但是使用pop_back、erase、clear等成员函数的时候,并不会减少实际capacity,只是删除vector中的元素

  • 向vector中新加入一个元素,比如使用push_back函数,当size大于capacity时,vector会重新找一块更大的内存,再把数据放进去。申请一块新的内存,把之前内存里面的元素拷贝到新内存中,把push_back的元素拷贝到新内存中,析构原有vector,释放原有内存

  • vector支持快速的随机访问,vector中的元素以连续方式存放。当向vector添加一个元素的时候,为了满足连续存放的特性,需要重新分配空间、拷贝元素、撤销旧空间,这样性能难以接受。STL底层对vector进行内存分配时,实际分配的capacity要比当前所需要的size要大一些,即预留了一些额外的存储区,用于存放新添加的元素,这样就不必为每个新元素重新分配整个容器的内存空间

vector定义与内存分配
  • 类外定义

    //一维vector
    vector a(10);
    //二维vector
    vector> b(3, vector(3, 0));
    
  • 类中定义

    不能使用以上类外两种定义方式

    //一维vector,无法指定列长
    vector a{1, 2, 3};
    //二维vector,无法指定列长
    vector b(3, vector{1, 2, 3});
    
vector定义方式
  • 一维vector

    • 一开始知道列长

      vector a(3, 0);
      
    • 一开始不知道列长,resize函数,实现按需分配

      vector b;
      b.resize(20);
      
    • 一开始不知道列长,reverse函数和push_back函数,不建议使用,push_back函数可能带来内存溢出

      vector c;
      c.reserve(25);
      for (int i = 0; i < 25; i++) {
          c.push_back(i);
      }
      
  • 二维vector(类中定义)

    • 一开始知道行列信息,resize函数,按需分配

      vector> d(5);
      for (int i = 0; i < d.size(); i++) {
          d[i].resize(10);
      }
      

      当对空的vector采取resize,capacity=size

      对于一个已有元素的vector进行resize,或者resize之后的vector,push_back了一些元素,那么会触发内存预留机制

vector清空元素与内存释放
  • vector的内存空间只增不减,初始化含有100个元素的vector,然后erase掉99个,留下一个有效元素,内存占用仍为100。内存空间是在vector析构时才被系统回收,同样使用clear之后,vector所占的内存空间依然不变

  • vector的内存空间只增加不减少,erase和clear只是减少了size,并不会减少capacity,所以内存空间没有减少,使用swap可以释放内存空间

  • vector()使用vector默认的构造函数建立临时vector对象,在该临时对象上调用swap成员,swap调用之后,原来的vector占用的空间就等于一个默认构造的对象的大小,临时对象就是原来对象的大小,而该临时对象随即就会被析构,从而占用的空间也被释放

    //swap成员函数清空vector容器
    vector().swap(x);
    //构造的时候没有传递任何参数,意味着表达式调用的是vector模板类的默认构造函数,不是拷贝构造函数。生成一个空的vector,再借助swap函数将容器交换给x,清空x
    
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/313252.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号