天天看点

Effective C++之3 资源管理

资源为系统所拥有,在借用资源后必须归还给系统。主要的资源包括:内存、文件描述符、互斥锁、图形界面中的字型、数据库连接、网络socket。

条款13:以对象管理资源

在对象中用指针管理的内存(例如在运行过程中动态分配的内存),使用者极易遗忘其释放,或者很难把握其释放时间,从而造成内存泄露,可通过用对象管理资源来保证其正常的运行,即使用智能指针,在对象销毁时自动调用智能指针的内在方法来析构其指向的动态内存。

以对象管理资源有两个特点:

a)       获得资源后立即放进对象,也即可称为“资源获取时机便是初始化时机”(RALL),因为总是在获得一笔资源后于同一语句内用来初始化某个管理对象。

b)       管理对象运用析构函数确保对象被释放。即对象被销毁时其析构函数会自动被调用,于是资源释放。

主要的包括指针指针:析构函数自动释放器所指向的内存。

l  指针指针包括auto_ptr,如std::auto_ptr<sutdet> pStu(CreateStudent());其中student为类名,此处表示智能指针的类型但是通过拷贝构造函数和等号操作符来复制这种类型的指针时,上一个指针会变为NULL,即始终只能有一个指针指向对象。

l  其替代方案是使用“应用计数型智慧指针“(RCSP),如tr1::shared_ptr,其使用方法:

如std:: tr1::shared_ptr<sutdet> pStu(CreateStudent());

条款14:在资源管理类中小心copy行为

面对一个RAII对象被复制会发生什么情况的问题,即调用拷贝构造函数。有两种可能,禁止复制和对底层资源祭出应用计数法。

Class Lock

{

         Public:

                  Explicit Lock(Mutex* pm):mutexPtr(pm,unlock)    //构造并以unlock为删除器

{lock(mutexPtr.get());  

}

         Private:

                  Std::tr1::share_ptr<Mutex> mutexPtr;

}

MutexPtr的析构函数会在互斥器的引用次数为0时自动调用tr1::shared_ptr的删除器(本例为unlock),拷贝其对象会增加其引用计数。

复制RAII对象必须一并复制它所管理的资源,所以资源的copying行为决定RAII对象的copying行为。

条款15:在资源管理类中提供对原始资源的访问

Tr1::shared_ptr和auto_ptr都提供一个get成员函数,用来执行显示转换,也就是可以返回智能指针内部的原始指针。Int day = dayHeld(pInv.get);其中pInv为智能指针。

也可通过一个接口来封装这个显示转换,使其使用比较便捷,但是可能导致对资源应用的误用。

条款16:成对使用new和delete时要采取相同形式

l  当你使用new运算符时,有两件事情发生。第一:内存被分配出来;第二:针对此内存有一个或多个构造函数被调用。调用delete时同理,先析构后释放。

l  在申请时使用的数组形式,在释放时也应该采用数组形式,前后形式应该一致。

条款17:以独立语句奖罚newed对象置入智能指针

以独立语句将newed对象储存(置入)智能指针中。如果不这样做,一旦异常被抛出,有可能导致难以察觉的资源泄露。

因为如此可以将执行顺序固定为先动态分配内存、调用tr1::shared_ptr构造函数、调用功能函数。否则第二步和第三步的执行顺序并不能保证。

如processWidget(std::tr1::shared_ptr<widget> (new widget));

应当转换为:

std::tr1::shared_ptr<widget> pw(new widget);

processWidget(pw);

继续阅读