《More Effective C++》《异常——9、利用destructors避免泄露资源》

文章目录

  • 1、Terms9:利用destructors避免泄露资源
    • 1.1代码1.0
    • 1.2代码2.0
    • 1.3代码3.0
  • 2、总结
  • 3、参考

1、Terms9:利用destructors避免泄露资源

假设我正在为小动物收容所编写软件,每天收容所建立一个文件,包含当天它所管理的收容动物的资料信息,我所要做的就是读出这些文件然后对每个收容动物进行适当的处理。
举个栗子:

class ALA{
public:virtual void processAdoption()=0;...
};
class Puppy:public ALA{
public:virtual void processAdoption();...
};
class Kitten:public ALA{
public:virtual void processAdoption();...
};

为了完成处理工作,需要你有一个函数从文件中读取信息,然后根据文件中的信息产生相应的实例对象。所以我们需要声明这样的函数。

1.1代码1.0

//从s中读取信息,然后返回一个指针
//指向新建立的某种类型对象
ALA* readALA(istream& s);

程序的关键是processAdoption()函数,如下所示:

void processAdoptions(istream& dataSource){while(dataSource){                  //在有数据的情况下,一直读取ALA *pa = readALA(dataSource);  //得到动物pa->processAdoption();			//处理收容所的动物delete pa;					    //删除readALA返回的对象}
}

但是这份代码并不完美,如果代码执行到

pa->processAdoption();

抛出了一个异常怎么办,这样后面的程序都不会执行到,就会导致processAdoptions资源泄漏。因此需要在processAdoptions内部添加异常捕获。

1.2代码2.0

代码如下:

void processAdoptions(istream& dataSource){while(dataSource){                ALA *pa = readALA(dataSource); try{pa->processAdoption();	} catch(...){.     //捕获所有异常delete pa;   //避免内存泄漏throw;       //当异常抛出时,传递异常给调用者}	delete pa;      //当没有资源泄露时,回收资源					    }
}

使用try和catch对代码进行了一些小改动,为了保险写了双份清除代码:一个为正常的运行准备,一个为异常发生时准备。这种代码并不完美,看上去心烦而且难以维护,好像还存在着一点问题。

1.3代码3.0

上述代码还有改进空间,我们可以把总被执行的清除代码放入processAdoptions函数内的局部对象的析构函数里,这样可以避免重复书写清除代码。无论函数是如何退出的,函数返回时局部对象总是要被释放的。
具体做法就是用对象代替指针,当类指针对象被释放时,我们能让他的析构函数调用delete,其实就是智能指针(smart pointers),在这里可以不用智能指针,只需要一个pointer-like对象,在它离开生存空间时删除它所指向的对象。
代码如下:

template<class T>
class auto_ptr{
public:auto_ptr(T *p = 0):ptr(p){}  //保存ptr,指向对象~auto_ptr() {delete ptr;}    //删除ptr指向的对象
private:T *ptr;
};
void processAdaptions(istream& dataSource)
{while(dataSource){auto_ptr<ALA> pa(readALA(dataSource));pa->processAdoption();}
}

这个版本的processAdaptions做出了2点重要的改进:
(1)pa被声明为一个auto_ptr对象,而不是一个raw ALA*指针;
(2)在循环的结尾没有delete语句;
使用auto_ptr的思想是,用一个对象存储需要被自动释放的资源,然后依靠对象的析构函数来释放资源;这样的话不仅代码本身比较可靠,简单,而且日后维护起来也十分的方便。

2、总结

书山有路勤为径,学海无涯苦作舟

3、参考

《More Effective C++》