使用析构函数防止资源泄露
原则:
- 资源应该被封装在一个对象里,遵循这个规则,你通常就能避免在存在异常环境里发生
资源泄漏。 - 少用局部资源的raw指针。
问题
当从堆上建立对象,并使用指针调用对象的函数。在删除对象前,如果发生异常,可能会造成对象无法正常释放。
void processAdoptions(istream& dataSource)
{
while (dataSource) { // 还有数据时,继续循环
ALA *pa = readALA(dataSource); //得到下一个动物
pa->processAdoption(); //处理收容动物
delete pa; //删除 readALA 返回的对象
}
}
智能指针是将带对象的指针封装起来。当智能指针对象析构时,delete其所封装的raw指针。
其核心思想是用一个对象存储需要被自动释放的资源,然后依靠对象的析构函数来释放资源。
以auto_ptr为例:
template<class T>
class auto_ptr {
public:
auto_ptr(T *p = 0): ptr(p) {} // 保存 ptr,指向对象
~auto_ptr() { delete ptr; } // 删除 ptr 指向的对象
private:
T *ptr; // raw ptr to object
};
void processAdoptions(istream& dataSource)
{
while (dataSource) {
auto_ptr<ALA> pa(readALA(dataSource));
pa->processAdoption();
}
}
这种思想不只是可以运用在指针上,还能用在其它资源的分配和释放上。
// 这个函数会发生资源泄漏,如果一个异常抛出
void displayInfo(const Information& info)
{
WINDOW_HANDLE w(createWindow());
在 w 对应的 window 中显式信息
destroyWindow(w);
}
//一个类,获取和释放一个 window 句柄
class WindowHandle {
public:
WindowHandle(WINDOW_HANDLE handle): w(handle) {}
~WindowHandle() { destroyWindow(w); }
operator WINDOW_HANDLE() { return w; } // see below
private:
WINDOW_HANDLE w;
// 下面的函数被声明为私有,防止建立多个 WINDOW_HANDLE 拷贝
//有关一个更灵活的方法的讨论请参见条款 M28。
WindowHandle(const WindowHandle&);
WindowHandle& operator=(const WindowHandle&);
};