Effective C++(条款13-17)

来源:互联网 发布:鸟瞰图设计制作软件 编辑:程序博客网 时间:2024/05/26 02:55

条款13:以对象管理资源

把资源放进对象内,我们就可以依赖C++的“析构函数自动调用机制”确保资源被释放。

关键点在于:获得资源后立即放进管理对象;管理对象运用析构函数确保资源被释放。



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

实际上“以对象管理资源”的观念常被称为“资源取得实际便是初始化时机”(Resource Acquisition Is Initialization;RAII),通常使用auto_ptr 和shared_ptr指向被创建的对象。

两者有些不同:auto_ptr若通过coping 构造函数或copy assignment操作符复制它们,它们会变成null,而复制所得的指针将取得资源的唯一拥有权,所以一定要注意别让auto_ptr                             同时指向同一个对象;

                            shared_ptr在每次通过coping 构造函数或copy assignment操作符复制它们后,指针的引用计数加一,一个对象失效后计数减一,直至它的最后一个使用者(某对                            象)被销毁,这个智能指针才会为空,它指向的对象才会被销毁。


auto_ptr和shared_ptr两者都在对象的析构函数内做delete而不是delete[]动作。


当一个RAII对象呗复制,会发生什么事情?有以下几种情况可供选择:

            禁止复制:如果复制动作对RAII类不合理,我们便应该禁止它,比如将copying操作声明为private

            对底层资源祭出“引用计数法”:有时候我们希望保有资源,直到它的最后一个使用者(某对象)别销毁,可以使用shared_ptr

            复制底部资源:复制资源管理对象时,应该同时也复制其所包覆的资源,也就是进行深度拷贝

            转移底部资源的拥有权:某些场合下你可能希望确保永远只有一个RAII对象指向一个未加工资源,即使RAII对象被复制依然如此,此时资源的拥有权会从被复制物转移到                                                        目标物。auto_ptr奉行的复制意义就是如此


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



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

对原始资源的访问可能经由显式转换或隐式转换,一般而言显式转换比较安全,但隐式转换对客户比较方便



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

new:分配内存—>调用构造函数

delete:调用析构函数—>释放内存

new和delete、new[]和delete[]要采用相同的形式成对使用




条款17:以独立语句将新建的对象置入智能指针

processWidget(std::tr1::shared_ptr<Widget>(new Widget),priority());

以上述语句为例,在调用processWidget之前,编译器必须创建代码,做一下三件事:

a.调用priority

b.执行new Widget

c.调用tr1::shared_ptr构造函数

那么c++是以怎么样的次序完成这些事情呢?弹性很大。如果是以这样的操作顺序:b->a->c,设想一下,万一对priority的调用导致异常,那么由new Widget返回的指针不能被置入到tr1::shared_ptr内,这样在对processWidget调用的过程中就可能会引发资源泄露,因为在“资源被创建”和“资源被转化为资源管理对象”两个时间点之间可能会发生异常干扰。


避免此类问题的方法很简单:使用分离语句将新建对象存储于(置入)智能指针内,如果不这样做,一旦异常抛出,有可能导致难以察觉的资源泄露。

std::tr1::shared_ptr<Widget>pw(new Widget);processWidget(pw,priority());


0 0
原创粉丝点击