现在的位置: 首页 > 综合 > 正文

effective C++ 读书笔记 条款14 以对象管理资源

2016年02月04日 ⁄ 综合 ⁄ 共 1993字 ⁄ 字号 评论关闭

假设我们使用一个投资行为的程序库:

#include "stdafx.h"
#include <iostream>
#include <memory>
using namespace std;
class  Investment
{
public:
};
class InvestmentFactory
{
public:
	virtual Investment* createInvestment()
	{
		Investment * inV = NULL;
		return inV;
	}
};
//第一版,这里可能发生内存泄露,比如在调用createInvestmen()之后到delete pInv之间的函数体之间发生了异常或者调用了return等
//那么delete语句将不会被执行,早成内存泄露
void f()
{
	InvestmentFactory fac;
	Investment* pInv = fac.createInvestment();

	delete pInv;
}

int _tmain(int argc, _TCHAR* argv[])
{
	return 0;
}

//第一版,这里可能发生内存泄露,比如在调用createInvestmen()之后到delete pInv之间的函数体之间发生了异常或者调用了return等

//那么delete语句将不会被执行,早成内存泄露

<span style="color:#3333ff;">void f()
{
	InvestmentFactory fac;
	Investment* pInv = fac.createInvestment();

	delete pInv;
}</span>

//第二版:为了确保createInvestment返回的资源总是被释放,我们需要将资源放进对象内,当控制流离开f,该对象的析构函数会自动释放那些资源
//auto_ptr是个类指针对象,也就是所谓的“智能指针”,其析构函数会自动对其所指对象调用delete。

<span style="color:#3333ff;">void f()
{
	InvestmentFactory fac;
	std::auto_ptr<Investment> pInv(fac.createInvestment());//调用factory函数,一如既往的使用pInv,经由auto_ptr的析构函数自动删除pInv
}</span>

//上面第二版“以对象管理资源”的两个关键想法

1:获得资源后立即放进管理对象:以上代码createInvestmen返回的资源被当做其管理者auto_ptr的初值。对象资源管理的观念也被称为
资源取得实际便是初始化时机,因为我们总是在获得一笔资源后于同意语句内以它初始化某个管理对象
2:管理对象运用析构函数确保资源被释放

//第二版存在的问题:
//由于auto_ptr被销毁时会自动删除它所指之物,所以一定要注意别让多个auto_ptr同时指向某一对象,如果真是这样,对象会被删除一次以上,程序
//出现未定义行为,为了防止这个问题,auto_ptr有一个不寻常的性质:若通过copy构造函数或者copy assigment操作符复制他们,他们会变为null
//而复制所得的指针将取得资源的唯一所有权。
auto_ptr<Investmen> pInv1(fac.createInvestment()); pInv1指向资源
auto_ptr<Investment> pInv2(pInv1); pInv2指向资源pInv1为NULL
pInv1 = pInv2; pInv1指向对象,pInv2成为null

//第三版:

<span style="color:#3333ff;">void f()
{
	InvestmentFactory fac;
	std::shared_ptr<Investment> pInv1(fac.createInvestment());//调用factory函数,一如既往的使用pInv,经由shared_ptr的析构函数自动删除pInv

	tr1::shared_ptr<Investment> pInv2(pInv1);//pInv1 和 pInv2 指向一个资源对象
	pInv2 = pInv1;//同上,无任何改变

	//当pInv1 and pInv2 销毁的时候,它们所指的对象也被自动销毁
}</span>

/*
第三版可以正常使用,也是最佳版本。 但是注意auto_ptr and shared_ptr在析构函数当中都是做的 delete而不是delete[],所以不要把
动态分配而得的array用在auto_ptr and shared_ptr身上。
*/

 

总结:

为防止资源泄露,请使用对象管理资源,他们在构造函数当中获得资源,并在析构函数当中释放资源

两个常用的RAII class 为 tr1::shared_ptr and auto_ptr;第一个是最佳选择因为其copy行为比较直观,若选择auto_ptr复制动作会使得它指向null;

抱歉!评论已关闭.