【C++】--遇到抛异常没有及时释放的空间该怎么办??---智能指针来帮你解决(以及定制删除器)

在这里插入图片描述

💖作者:小树苗渴望变成参天大树🎈
🎉作者宣言:认真写好每一篇博客💤
🎊作者gitee:gitee
💞作者专栏:C语言,数据结构初阶,Linux,C++ 动态规划算法🎄
如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧!


前言

今天我们来讲解一个好理解,有好用的知识点–智能指针。智能指针有很多种,但是每种都有相同之处,一会按顺序介绍的哦都是每一种的补充,他的作用是解决没有办法再回头来释放的空间,导致会内存泄漏,所以需要指针指针来解决这个问题,话不多说,我们开始进入正文讲解


一、为什么设计出智能指针??

再以前是没有智能指针的东西,那为什么现在设计出来了看代码:

void f()
{
   
	pair<string, string>* p1 = new pair<string, string>;//可能会出现错误抛异常
	fun();
	delete p1;
}
int main()
{
   
	f();
	return 0;
}

以前我们申请空间就释放空间,中间有啥都无所谓,肯定没有问题的,但是异常出来之后,就会导致fun出现异常,这时候就会影响执行流,可能会释放不到p1,这样就导致内存泄漏,

**那我们的java有没有智能指针呢??**答案是没有的,他有垃圾回收器,可以自动回收内存,那C++为什么不搞呢??原因就是c++程序是直接跑在os上的,而Java先再虚拟机上跑,而虚拟机再os上跑,多了一层,所以C++想要直接去搞垃圾回收器是一件很耗成本的事,有便宜就有付出,所以再一些追求性能的程序,大部分都选择C++比如游戏,遥控器需要及时响应的。并且C++程序和os是直接互通的


有了异常来说我们来看下面的代码:

(1)

int div()
{
   
	int a, b;
	cin >> a >> b;
	if (b == 0)
		throw invalid_argument("除0错误");

	return a / b;
}
void f()
{
   
	pair<string, string>* p1 = new pair<string, string>;//可能会出现错误抛异常

	try
	{
   
		div();//正常执行逻辑
	}
	catch (...)//接收任意类型的异常
	{
   
		cout << "delete:" << p1 << endl;
		delete p1;//先释放
		throw;//抛出去
	}
}
int main()
{
   
	try
	{
   
		f();
	}
	catch (const exception& e)//捕获抛出来的异常
	{
   
		cout << e.what() << endl;
	}
	return 0;
}

大家仔细看我们的f函数里面有一块动态申请的空间,如果div里面抛异常的,我们再抛出去之前就给释放就可以解决问题。也是可以解决问题的。
在这里插入图片描述
这就是由于异常那个出现导致执行流的变化。

(2)将上面的f()函数改成下面这样看看,其余不变。

void f()
{
   
	pair<string, string>* p1 = new pair<string, string>;//可能会出现错误抛异常
	pair<string, string>* p2 = new pair<string, string>;
	try
	{
   
		div();//正常执行逻辑
	}
	catch (...)//接收任意类型的异常
	{
   
		cout << "delete:" << p1 << endl;
		delete p1;//先释放
		throw;//抛出去
	}

	cout << "delete:" << p1 << endl;
	delete p1;
	cout << "delete:" << p2 << endl;
	delete p2;
}

我给大家来分析一下,再申请的时候也可能出现申请失败,概率很小但有可能,此时p1申请失败,那下面的代码就不会执行,退出函数,也不存申请内存释放问题,万一p1申请成功,执行申请p2的时候出现了异常,退出了函数,那么刚申请的p1就没有办法释放,有人说给p2也加一个异常处理:

void f()
{
pair<string, string>* p1 = new pair<string, string>;//可能会出现错误抛异常
pair<string, string>* p2 = new pair<string, string>;//可能会出现错误抛异常
try//是p2的异常捕获
{
	;//正常执行逻辑
}
catch (...)//接收任意类型的异常
{
	cout << "delete:" << p1 << endl;
	delete p1;//先释放
	throw;//抛出去
}
try//是div的异常捕获
{
	div();//正常执行逻辑
}
catch (...)//接收任意类型的异常
{
	cout << "delete:" << p1 << endl;
	delete p1;//先释放
	throw;//抛出去
}
cout << "delete:" << p1 << endl;
delete p1;
cout << "delete:" << p2 << endl;
delete p2;
}

上面代码可以解决我说的场景,但是出现下面的场景呢?
>

内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现
内存泄漏会导致响应越来越慢,最终卡死
所以针对可能造成内存泄漏的空间,我们不可能每一个都要捕获一下异常,所以针对这个问题我们要想办法解决,这才引入了智能指针

二、智能指针的使用及原理

相信通过上面的例子,大家应该明白C++11要搞出智能指针了吧,接下来我将带大家来学习智能指针。

2.1 最简单的智能指针

在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在
对象析构的时候释放资源。借此,我们实际上把管理一份资源的责任托管给了一个对象。这种做
法有两大好处:
不需要显式地释放资源。
采用这种方式,对象所需的资源在其生命期内始终保持有效

我们抛出异常就意味结束了此函数,想要解决释放,将指针写成一个类,自动调用析构函数,就可以了,来看代码:

class smartptr
	{
   
	public:
		smartptr(pair<string, string>* sp)
			:_ptr(sp)
		{
   
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

橘柚!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值