面向对象编程之RAII

 

【问题起源】
假设有这么个函数:

看起来似乎没什么问题。但是面向对象里有异常这么回事,如果一个异常抛出又没被处理,就会直接退出该级函数到上一层去。如果dosomething()中有异常抛出,这里delete p就不会被执行,造成资源泄露。为了解决这个问题,就得手工在异常处理里delete一遍:

 

然而这么写实在是麻烦。

【解决方案】RAII
RAII是Resource Acquisition Is Initialization的缩写,中文是资源获得式初始化。它利用了栈上的变量会被自动销毁的事实。

 

这时如果dosomething有异常抛出,p作为栈上的局部变量会被自动销毁,~PtrClass()会被自动调用,于是可以保证 new出来的int *会被销毁。

【应用二】
就算不考虑异常安全,这种技术也可以带来便利:

 

这里foo_1(), foo_2(), foo_3()是别处定义好的函数,如果返回真则foo()没有必要再往下走。那么多delete a就是为了保证不资源泄露。(我们先不讨论这个函数是否会有更好的设计方案。)如果采用上面的RAII就不用这么麻烦了。这里只有一个指针,可能看起来简单;不妨想象一下有100个new出来的指针需要删除的情况,foo_n()有100个的情况。。。。

【应用三】多线程锁
多线程编程里,有时候会出现加锁之后忘了解锁的情况:

这里的麻烦仍然在于异常。如果DoSomething()抛出异常,这里有没有处理,那么mutex就永远处于被锁住的状态了。这时候如果应用RAII,就没有这样的问题了:

因为异常退出时所有栈上的局部变量会被自动销毁,所以mutex会被解锁。

提个问题:这里 myMutex m(mutex); 有没有可能让编译器给优化掉?

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值