[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<int> a(10);
    //二维vector
    vector<vector<int>> b(3, vector<int>(3, 0));
    
  • 类中定义

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

    //一维vector,无法指定列长
    vector<int> a{1, 2, 3};
    //二维vector,无法指定列长
    vector<int> b(3, vector<int>{1, 2, 3});
    

vector定义方式

  • 一维vector

    • 一开始知道列长

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

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

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

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

      vector<vector<int>> 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<int>().swap(x);
    //构造的时候没有传递任何参数,意味着表达式调用的是vector模板类的默认构造函数,不是拷贝构造函数。生成一个空的vector,再借助swap函数将容器交换给x,清空x
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值