c++vector容器的内存收缩和预留内存

本文介绍了C++中如何利用swap函数和匿名对象实现vector容器内存的即时回收,以及通过reserve预留内存减少容器动态扩展的次数,提升程序运行效率。

一:利用swap进行内存收缩

 

引言:利用swap函数和匿名对象来实现对容器所占用内存的及时回收 

#include<iostream>
#include<vector>
using namespace std;
void test01(){
	vector<int>v;
	for(int i=0;i<1000000;i++)   //容器的容量相当大,并且占用的内存也很大 
	    v.push_back(i);
	cout<<"容器容量         "<<v.capacity()<<endl;
	cout<<"容器当前元素个数 "<<v.size()<<endl;
	    
	v.resize(10);//利用resize函数重新确定了元素个数,可以看出resize后容器容量很大,但实际用到的很少,这时候就得用到内存收缩
	cout<<"内存收缩之前:    "<<endl;  

	cout<<"容器容量         "<<v.capacity()<<endl;
	cout<<"容器当前元素个数 "<<v.size()<<endl; 
	
	vector<int>(v).swap(v);  //关键的内存收缩语句

	cout<<"内存收缩之后:    "<<endl;  

	cout<<"容器容量         "<<v.capacity()<<endl;
	cout<<"容器当前元素个数 "<<v.size()<<endl;
}
int main() {
	test01();
}

 关键代码分析:vector<int>(v).swap(v); 

前半部分vector<int>(v)就是一个匿名对象,通过拷贝构造函数来利用用已有容器中的元素来为其初始化,但是此匿名对象的capacity就是之前容器的size,然后再调用swap函数就能把两个容器所有的全部互换,而匿名对象的生存期只是这一行代码,到下一行代码就会被系统自动收回,这样就巧妙地完成了容器内存的收缩,

 

二:预留内存

为什么要预留内存?

我们已经知道,c++vector容器在创立之初并未指定容量,他的容量是系统自动计算分配的。当容量不够时,编译器不会在容器后面直接接上一段,而是会直接再开辟一块新的比之前大一些的内存来存放扩大后的容器,然后把之前的那块内存释放掉。

               因此如果数据量较大,可以一开始利用reserve预留空间

功能描述:

  • 减少vector在动态扩展容量时的扩展次数

函数原型:

  • reserve(int len);//容器预留len个元素长度,预留位置不初始化,元素不可访问。

示例代码: 

          1.未预留时:

#include<iostream>
#include<vector>
using namespace std;
void test01(){
      vector<int>v;
      int times=0; //记录开辟次数
      int *p; //通过和times的配合使用来记录容器开辟内存的次数 
	  for(int i=0;i<100000;i++){
	  	v.push_back(i);
	  	if(p!=&v[0]) 
	  	   { 
	  	    p=&v[0];
	  	   	times++;
			 }
	  } 
	  
	  cout<<"内存开辟次数为"<<times<<endl;
}
int main() {
	test01();
}

不难看出,系统开辟了十八次内存,这是非常费工夫的,影响了程序的运行效率,所以我们要尽量减少内存的开辟次数,这就用到了内存的预留。

           2.预留后

#include<iostream>
#include<vector>
using namespace std;
void test01(){
      vector<int>v;
      int times=0; //记录开辟次数
      int *p; //通过和times的配合使用来记录容器开辟内存的次数 
      
      v.reserve(100000);  //预留操作 

	  for(int i=0;i<100000;i++){
	  	v.push_back(i);
	  	if(p!=&v[0]) 
	  	   { 
	  	    p=&v[0];
	  	   	times++;
			 }
	  } 
	  
	  cout<<"内存开辟次数为"<<times<<endl;
}
int main() {
	test01();
}

### C++ 中 `vector` 正确释放内存与资源管理的最佳实践 #### 使用析构函数自动清理 当不再需要 `std::vector<int>` 对象时,其生命周期结束会触发默认析构函数执行。该过程能够确保所有已分配给向量内部数组的空间被适当地回收[^1]。 ```cpp { std::vector<int> vec; // 向vec添加元素... } // 当作用域结束时,vec及其持有的资源会被销毁并释放 ``` #### 明确清空内容而不立即减少容量 如果希望保留当前预留空间以便后续重用,则可以仅清除现有条目而不停留于缩小实际占用字节数: ```cpp // 清除所有元素但保持预分配大小不变 myVector.clear(); assert(myVector.empty()); ``` #### 手动收缩至合适尺寸 为了使容器的实际存储匹配逻辑长度,在某些情况下可显式请求调整底层数组规模: ```cpp void shrink_to_fit_example(){ std::vector<double> data(10); // ...操作data... // 提示编译器尝试优化内存使用效率 data.shrink_to_fit(); } ``` #### 利用交换技巧完全腾退 对于那些确实想要即时放弃整个缓冲区的情况——即使这可能导致频繁重新配置新区域的风险——可以通过标准库提供的swap惯用法达成目的[^5]: ```cpp template<typename T> void release_vector_memory(std::vector<T>& v){ using namespace std; vector<T>().swap(v); // 创建临时空对象并与原实例互换所有权 } ``` 上述方法遵循现代C++编程中的RAII原则(Resource Acquisition Is Initialization),即通过构造破坏局部实体来控制资源获取与释放的时间点,从而有效预防潜在泄漏问题的发生.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ad_m1n

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值