09-利用destructors避免资源泄露
第三章,异常
条款9 利用destructors避免资源泄露
为什么需要使用Exception?
如果函数只是返回错误码或发出一个异常信号,无法确保函数调用者会检查返回的错误码,使得程序保留错误隐患继续运行下去;但是如果函数以抛出exception的方式发出异常信号,而该exception未被捕捉,程序的执行便会立即中止。
本章的条款并不能架构完全的”exception-safe软件”设计指南,但只要留意这些指引就可以改善软件的正确性、稳健性、效率,并且可以避开很多因exception产生的问题。
利用destructors避免资源泄露
小动物收养保护中心的类的设计例子
class ALA |
可以看到, delete pa;是防止资源泄漏的必要代码;现在考虑一种情况:如果pa->processAdoption()抛出exception,会发生什么?
由于processAdoptions函数内部没有try,catch,因此没有捕捉到异常,该异常会传播到processAdoptions的调用端。当pa->processAdoption()抛出了一个未被捕获的异常时,那么紧跟在它后面的 delete pa; 永远不会被执行,造成资源泄露!
为避免以上的情况发生,可以修改为以下代码:
//程序核心函数: |
但是上面的代码仍然有让人不满意的地方,一是try catch语句“分裂”了程序语句,难看;再者是delete pa重复编写,这些都是提升了程序代码的维护难度。
那是否有更优雅的设计呢?
当然是有的,那就是将delete pa这样的清理操作移到processAdoptions中使用的某个局部对象的析构函数destructor内即可(栈上局部对象要销毁时自动调用析构函数完成清理工作)。下面详细说一下怎么做:
可以使用auto_ptr代替直接使用pa指针来实现这个思路,auto_ptr是C++标准库提供的一个class template;其构造函数要求得到一个指向heap object的指针,其析构函数会将该heap object删除。(嗯,像是一个指针保姆,管家?) 只涉及以上两点的话,auto_ptr看起来就像下面的代码:
template<class T> |
以auto_ptr对象取代原始指针后:
void processAdoptions(istream& dataSource) |
这个例子背后的观念尤为重要: 以一个对象存放“必须自动释放的资源” ,并依赖该对象的析构函数释放!
