💖作者:小树苗渴望变成参天大树🎈
🎉作者宣言:认真写好每一篇博客💤
🎊作者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)
{