【C++】智能指针

前言

本篇为C++最后一篇,我们来一起看看智能指针的内容,来明白智能指针的原理,以及用途.

💓 个人主页:小张同学zkf

⏩ 文章专栏:C++

若有问题 评论区见📝

🎉欢迎大家点赞👍收藏⭐文章

 

 

目录

 1.智能指针的使用场景分析

2.RAII和智能指针的设计思路

3.C++标准库智能指针的使用

4.智能指针的原理

5.shared_ptr和weak_ptr

5.1shared_ptr循环引用问题

5.2weak_ptr

6.shared_ptr的线程安全问题

7.C++11和boost中智能指针的关系


 1.智能指针的使用场景分析

下⾯程序中我们可以看到,new了以后,我们也delete了,但是因为抛异常导,后⾯的delete没有得到执⾏,所以就内存泄漏了,所以我们需要new以后捕获异常,捕获到异常后delete内存,再把异常抛出,但是因为new本⾝也可能抛异常,连续的两个new和下⾯的Divide都可能会抛异常,让我们处理起来很⿇烦。智能指针放到这样的场景⾥⾯就让问题简单多了。
double Divide ( int a, int b)
{
// b == 0 时抛出异常
if (b == 0 )
{
throw "Divide by zero condition!" ;
}
else
{
return ( double )a / ( double )b;
}
}
void Func ()
{
// 这⾥可以看到如果发⽣除 0 错误抛出异常,另外下⾯的 array array2 没有得到释放。
// 所以这⾥捕获异常后并不处理异常,异常还是交给外⾯处理,这⾥捕获了再重新抛出去。
// 但是如果 array2new 的时候抛异常呢,就还需要套⼀层捕获释放逻辑,这⾥更好解决⽅案
// 是智能指针,否则代码太戳了
int * array1 = new int [ 10 ];
int * array2 = new int [ 10 ]; // 抛异常呢
try
{
int len, time;
cin >> len >> time;
cout << Divide (len, time) << endl;
}
catch (...)
{
cout << "delete []" << array1 << endl;
cout << "delete []" << array2 << endl;
delete [] array1;
delete [] array2;
throw ; // 异常重新抛出,捕获到什么抛出什么
}
// ...
cout << "delete []" << array1 << endl;
delete [] array1;
cout << "delete []" << array2 << endl;
delete [] array2;
}
int main ()
{
try
{
Func ();
}
catch ( const char * errmsg)
{
cout << errmsg << endl;
}
catch ( const exception& e)
{
cout << e. what () << endl;
}
catch (...)
{
cout << " 未知异常 " << endl;
}
return 0 ;
}

 


2.RAII和智能指针的设计思路

RAII是Resource Acquisition Is Initialization的缩写,他是⼀种管理资源的类的设计思想,本质是
⼀种利⽤对象⽣命周期来管理获取到的动态资源,避免资源泄漏,这⾥的资源可以是内存、⽂件指
针、⽹络连接、互斥锁等等。RAII在获取资源时把资源委托给⼀个对象,接着控制对资源的访问,
资源在对象的⽣命周期内始终保持有效,最后在对象析构的时候释放资源,这样保障了资源的正常
释放,避免资源泄漏问题。
智能指针类除了满⾜RAII的设计思路,还要⽅便资源的访问,所以智能指针类还会想迭代器类⼀
样,重载 operator*/operator->/operator[] 等运算符,⽅便访问资源。
template < class T >
class SmartPtr
{
public :
// RAII
SmartPtr (T* ptr)
:_ptr(ptr)
{}
~ SmartPtr ()
{
cout << "delete[] " << _ptr << endl;
delete [] _ptr;
}
// 重载运算符,模拟指针的⾏为,⽅便访问资源
T& operator *()
{
return *_ptr;
}
T* operator ->()
{
return _ptr;
}
T& operator []( size_t i)
{
return _ptr[i];
}
private :
T* _ptr;
};
double Divide ( int a, int b)
{
// b == 0 时抛出异常
if (b == 0 )
{
throw "Divide by zero condition!" ;
}
else
{
return ( double )a / ( double )b;
  }
}
void Func ()
{
// 这⾥使⽤ RAII 的智能指针类管理 new 出来的数组以后,程序简单多了
SmartPtr< int > sp1 = new int [ 10 ];
SmartPtr< int > sp2 = new int [ 10 ];
for ( size_t i = 0 ; i < 10 ; i++)
{
sp1[i] = sp2[i] = i;
}
  int len, time;
  cin >> len >> time;
cout << Divide (len, time) << endl;
}
int main ()
{
try
{
Func ();
}
catch ( const char * errmsg)
{
cout << errmsg << endl;
}
catch ( const exception& e)
{
cout << e. what () << endl;
}
catch (...)
{
cout << " 未知异常 " << endl;
}
return 0 ;
}

3.C++标准库智能指针的使用

C++标准库中的智能指针都在<memory>这个头⽂件下⾯,我们包含<memory>就可以是使⽤了,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值