C++Primer : 第十二章 :智能指针和异常

智能指针和异常
即时程序块过早结束,智能指针类也能确保在内存不再需要时将其释放

void f(){
	shared_ptr<int> sp(new int(42));   //分配一个新对象
	//这段代码抛出一个异常,且在f中未被捕获
}   //在函数结束时shared_ptr自动释放内存

与之对应的,当发生异常时,我们直接管理的内存是不会自动释放的。如果使用内置指针管理内存,且在new之后在对应的delete之前发生了异常,则内存是不会被是释放的。

void f(){
	int *ip = new int(42);   //动态分配一个新对象
	//这段代码抛出异常,且在f中未捕获
	delete ip;    //在退出之前释放内存
}

如果在new和delete之间发生异常,且异常未在f中被捕获,则内存就永远不会被是释放了。在函数f之外没有指针指向这块内存

智能指针和哑类
假如,我们正在使用一个C/C++都使用的网络库,代码如下:

struct destination;    //表示我们正在连接着什么
struct connection;     //使用连接所需信息
connection connect(destination *);   //打开连接
void disconnect(connection);         //关闭给定连接
void f(destination &d /*其他参数*/){
	//获得一个连接,记住使用完要关闭它
	connection c = connect(&d);
	//使用连接
	//如果我们在f退出前忘记调用disconnect,就无法关闭c了
}

对于这个问题,我们使用share_ptr来保证connection被正确关闭
当一个shared_ptr被销毁时,它默认地对它管理地指针进行delete操作。为了用shared_ptr来管理一个connection,我们必须首先定义一个函数来代替delete。这个删除器函数必须能够完成对shared_ptr中保存的指针进行释放操作。在本例中,我们的删除器必须接受单个类型为connection*的参数。

void end_connection(connection *p){disconnect(*p);}

当我们创建一个shared_ptr时,可以传递一个指向删除器函数的参数

void f(destination &d /*其他参数*/){
	connection c = connect(&d);
	shared_ptr<connection> p(&c, end_connection);
	//使用连接
	//当f退出时,connection会被正确关闭
}

当p被销毁时,它不会对自己保存的指针执行delete,而是调用end_connection。end_connection会调用disconnect,从而确保连接被关闭。如果发生了异常,p同样会被销毁,从而连接被关闭

编写自己版本用shared_ptr管理connection的函数,并用lambda代替end_connection函数

#include <iostream>
#include <memory>
using namespace std;
struct destination {};
struct connection {};
connection connect(destination* pd) {
	cout << "打开连接" << endl;
	return connection();
}
void disconnect(connection c) {
	cout << "关闭连接" << endl;
}
//未使用shared_ptr的版本
void f(destination& d) {
	cout << "直接管理connect" << endl;
	connection c = connect(&d);
	//忘记调用disconnect关闭连接
	cout << endl;
}
void end_connection(connection* p) { disconnect(*p); }
//lambda不捕获局部变量,参数为connection指针,用改指针指向的对象调用disconnect即可
//[](connection *p){disconnect(*p);}
void f1(destination& d) {
	cout << "用shared_ptr管理connect" << endl;
	connection c = connect(&d);
	shared_ptr<connection> p(&c, end_connection);
	//shared_ptr<connection> p(&c,[](connection *p){disconnect(*p);} );
	//忘记调用disconnect关闭连接
	cout << endl;
}
int main() {
	destination d;
	f(d);
	f1(d);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值