利用Destructor避免泄漏资源

异常存在的理由:如果一个函数利用“设定状态变量”的方式或是利用“返回错误码”的方式发出一个异常信号,无法保证此函数的调用者会检查那个变量或检验那个错误码。于是程序可能会一直继续下去,远离错误发生地点。但是如果函数以抛出expcetions的方式发出异常信号,而该exception未被捕捉,程序的执行便会立刻中止。

longjmp在C++中有一个严重的缺陷:当它调整栈(stack)的时候,无法调用局部(local)对象的destructors。大部分C++程序很依赖这些destructor被调用,所以setjmp和longjmp对真正的exceptions而言不是个良好的替代品。

class ALA
{
public:
virtual void process()=0;
...
};

class Puppy : public ALA
{
public:
virtual void process();
...
};

class Kitten : public ALA
{
public:
virtual void process()
....
};


//process函数体
void process(istream& dataSource)
{
while( dataSource )
{
ALA *pa = readALA(dataSource);
pa->process();
delete pa;
}
}

如果函数在pa->process()函数抛出异常,process()无法捕捉它,这个异常会传播到process的调用端。pa->process()之后的语句都不会被调用,不再执行,从而也导致资源泄漏。
避免方法:
void  process(istream& dataSource)
{
while( dataSource )
{
ALA *pa = readALA(dataSource);
try
{
pa->process();
}
catch(...)
{
delete pa;
throw;
}
delete pa;
}
}
上面函数的代码显得凌乱不堪,更重要的是,被迫重复撰写其实可被正常路线和异常路线共享的清理代码,本例指的是delete动作。这为程序的维护带来麻烦,我们要做的事情就是在程序以正常或非正常方式离开函数时,都需要删除pa。何不集中于一处做这件事呢。
只要我们能够将“一定得执行的清理代码”移到process函数的某个局部对象的destructor内即可。因为局部对象总是会在函数结束时被析构,不论函数如何结束。如何把delete动作从process函数移到函数内某个局部对象的destructor内。
解决办法是,以一个类似指针的对象取代指针pa。“行为类似指针(但动作更多)”的对象我们称为smart pointer。
C++中的auto_ptr类模板,其行为正好可以解决我们的问题。auto_ptr看起来像这样:
template<class T>
class auto_ptr
{
public:
auto_ptr(T *p = 0 ):ptr(p) {}
~auto_ptr() { delete ptr; }
private:
T* ptr;
};
由于auto_ptr destructor采用“单一对象”形式的delete,所以auto_ptr不适合取代数组对象的指针。
新版本的函数
void process(istream& dataSource)
{
while( dataSource )
{
auto_ptr<ALA> pa(readALA( dataSource ));
pa->process();
}
}
隐藏在auto_ptr背后的观念--以一个对象存放“必须自动释放的资源”,并依赖该对象的destructor释放--亦可以“以指针为本”以外的资源施行。
坚持一个原则:把资源封装在对象内,通常便可以在exceptions出现时避免泄漏资源。

More Effective C++----9th

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值