条款13:以对象管理资源

(一)

如下代码,假设各种子类型继承 root class Investmen:

class Investment {...};
Investment* createInevstment();  //factory函数

void f() {
	Investment* pInv = createInvestment();
	...;
	delete pInv;  //释放pInv所指的对象
}

在”...”区域内一个过早return,或者期间抛出异常,流程控制不可能经过这条语句,所以这样的话就会导致资源泄露。

解决方法:

为了确保createInvestment返回的资源总是被释放,我们需要将资源放进对象内,当控制流离开函数f的时候,对象的析构函数会自动释放那些资源。把资源放进对象,我们便可以依赖C++的“析构函数自动调用机制“确保资源被释放。


智能指针:auto_ptr是个”类指针对象“,其析构函数自动对其所指对象调用delete

class Investment{...};
Investment * createInvestment();// factory函数声明

void f()
{
	auto_ptr pInv(createInvestment());
	...;
} //经由auto_ptr 析构函数自动删除 pInv

1 createInvestment() 以资源取得时便是初始化时,每一笔资源在获得同时立即被放进管理对象中。

2无论控制流如何离开区块,一旦对象被销毁,其析构函数自然被调用,遇事资源就被释放。


(二)

auto_ptr有个性质:若通过copy构造函数或者copy assignment操作符赋值他们。他们会变成null,而赋值所得的指针将取得资源的唯一拥有权。

auto_ptr pInv1(createInvestment()); 
auto_ptr pInv2(pInv1);   //现在pInv2指向对象,pInv1被设为null 
pInv1 = pInv2;   //现在pInv1指向对象,pInv2被设为null
这个诡异的复制行为,使得要求其元素发挥”正常的“赋值行为的像stl容器容不得auto_ptr。

解决方法是使用:引用计数型智慧指针 shared_ptr


(三)

"引用计数型指针“。tr1::shared_ptr(比如 boost库里的 boost::shared_ptr.)他是个智能指针,持续追踪共有多少个对象指向某笔资源,并在没人指向它时,自动删除该资源。

void f() 
{ 
	tr1::shared_ptr pInv(createInvestment()); 
	... 
}//经由shared_ptr的析构函数
虽然看起来跟 auto_ptr相同。但是 shared_ptr的复制行为正常

void f() 
{ 
	tr1::shared_ptr pInv1(createInvestment()); 
	tr1::shared_ptr pInv2(pInv1);//pInv1和pInv2指向同一个对象 
	pInv1 = pInv2;   //同上,无任何改变
	... 
}//pInv1和pInv2被销毁,他们指向的对象也就被销毁。

(四) 

两种指针底层实现都是 delete 而不是delete[],所以不要把它们用在动态分配数组上。

vector 跟string几乎总是可以取代动态分配而得的数组。


请记住:

1 为了防止资源泄露,请使用RAII对象。它们在构造函数中获得的资源并在析构函数中释放资源。

2 两个常被使用的RAII classes 分别是 auto_ptr 和 tr1::shared_ptr。后者是较佳选择。因为copy行为直观。若选择auto_ptr,复制动作会使(被复制)指向null。






你可能感兴趣的:(Effective,C++)