STL容器vector的内存问题

本文详细介绍了STL中的Vector容器,包括其动态内存增长机制、迭代器失效问题、如何释放占用的内存以及预先分配内存的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      在STL的容器中,vector可以说是最容易理解和使用的容器了,以前使用数组的时候,如果不确定有多少数据要存储,就会预先分配一个大的数组,如果实际没有用到那么多,又会浪费很多的内存资源,如果不分配大的数组又担心不够用,有了vector之后,这些问题再也不用担心了,vector会动态的增长空间,当vector空间不足时会自动申请一片更大的内存空间,以存储新的数据。
       vector动态内存增长的过程如下:
       1) 申请一块更大的内存空间以存储新数据。
       2) 将数据从旧内存空间拷贝到新内存空间。
       3) 析构旧内存空间中的对象。
       4) 释放旧内存空间。
       对于程序员来说,这简直就是一个神器,但是在享受vector带来方便的同时,它也隐藏了一些内存方面的问题,需要我们注意一下。

1、预先分配两倍的内存空间

       对于一个数组,只要通过元素的个数以及元素的类型就可以得到占用的内存空间,而对于vector情况就不一样,为了提高效率,vector会预先分配一定的内存空间,减少申请内存以及数据移动的开销,因此vector实际占用的内存空间要比需要的多一些。
       如果对内存要求比较高的程序,使用vector一定要小心了,当vector空间不足时,会申请一块约是当前占用内存两倍的新空间以存储更多的数据,若可用内存为1G,而当前vector已占用的内存空间0.5G,当再插入一个元素,vector将会申请一块约1G的内存空间,瞬间内存就被用光了,导致程序崩溃。

2、迭代器失效

       当vector空间不足时,会申请一块更大的内存空间,并将原指向内存空间的数据移动到新的内存空间中,接着,旧的内存空间将会被回收。这里就可能会出现问题了,当vector指向新的内存空间之后,原来指向旧内存空间的迭代器都会失效了,若再使用这些失效迭代器,将会出现coredump。因为当需要插入数据到vector的时候,就需要注意当前的迭代器还是否有效了。

3、释放vector所占内存

       vector已经申请的内存空间并不会缩减,即使调用clear()函数,也只是清空vector的所有元素,真正占用的内存空间也不会减少。有一种方法可以释放vector占用的内存空间,swap()函数可以交换两个vector对象所指向的内存空间,
       下面例子说明了swap()函数的使用方法,假设拥有一个vector<int>对象vec:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. vector<int> tmp;  //tmp为空  
  2. vec.swap(tmp);      //vec和tmp交换指向的内存空间  

       如果代码想要更加精简,则可以选择下面的写法:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. vec.swap(vector<int>());//vec与临时对象交换了指向的内存空间  

       上面两种方式都使用一个没有数据的vector对象与当前vetor对象进行了交换,对于vec来讲,其内存空间缩减为0,同理,若想vec变为指定大小,则只需要与一个大小一样的vector对象进行swap即可。

4、预先申请内存空间

       若一开始就大概确定需要的内存空间,则可以使用vector的reserve()函数预先申请足够的内存空间,这样做,既可以减少内存增长时的申请内存和数据移动的开销,避免了迭代器失效的问题,也防止了申请了超出预期的的内存空间,导致内存耗尽的问题;若一开始不确定需要的内存空间,则可以先预留足够大的空间,当所有数据都插入后,通过swap()函数去除多余的容量即可。

### C++ STL Vector 容器特性 #### 动态调整大小 `std::vector` 是一种动态数组,能够自动管理内存并根据需要增长或收缩。当向 `vector` 中添加元素而超出当前容量时,会分配新的更大空间并将原有数据复制过去[^1]。 #### 随机访问支持 提供高效的随机存取能力,允许通过索引快速定位任意位置上的元素。这使得 `vector` 成为了实现其他复杂结构(如栈、队列)的理想选择之一[^2]。 #### 迭代器兼容性 具备完整的迭代器接口,可以方便地遍历整个序列,并且支持标准算法库中的各种操作。例如: ```cpp for (auto it = vec.begin(); it != vec.end(); ++it) { std::cout << *it; } ``` ### 使用方法 #### 创建实例 可以通过多种方式创建一个新的 `vector` 对象,包括但不限于以下几种形式[^3]: - 默认构造函数:`std::vector<int> myVec;` - 初始化列表:`std::vector<double> myDoubles{1.0, 2.0, 3.5};` - 复制现有容器的内容:`std::vector<char>(anotherVector.begin(), anotherVector.end());` #### 添加/删除元素 提供了丰富的成员函数用于修改内部存储的数据项,比如: - 插入单个新值到末尾:`myVec.push_back(42);` - 移除最后一个元素:`if (!myVec.empty()) myVec.pop_back();` - 清空所有条目:`myVec.clear();` #### 访问控制 除了常规下标运算符外,还存在专门的方法来安全获取特定偏移处的对象引用以及检查是否为空等实用功能: - 获取第一个元素:`myVec.front()` - 取得最后一个项目:`myVec.back()` - 判断是否有任何成分:`bool isEmpty = myVec.empty();`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值