您的位置:首页 > 其它

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

2009-06-15 10:08 381 查看
条款17:以独立语句将newed对象置入智能指针
(Store newed objects in smart pointers in standalone statements.)

内容:
假设现在我们需要一个函数去处理一个消息processMessage,它需要一个消息对象和一个消息处理函数,由此
我们遵循"对象管理资源"的原则,写出如下代码:
class WindowsMesssage{...};
int messageProcedure();
void processMessage(std::tr1::shared_ptr<WindowsMesssage> message,messageProcedure);
现在我们就来调用这个函数:
class PaintMessage:public WindowsMesssage{
...
};
//test.cpp
processMessage(new PaintMessage,messageProcedure);
这样调用,显然出现了原则性的问题:第一个参数与函数原型签名的第一个参数类型不匹配,又由于shared_ptr
构造函数是explicit所以说不能进行隐式转换,故这里我们这样写:
processMessage(std::tr1::shared_ptr<WindowsMesssage>(new PaintMessage),messageProcedure);
我们现在来关注一下,在真正调用processMessage之前,编译器准备工作做了哪些?其实它做了三件事情:
(1)调用messageProcedure;
(2)执行new PaintMessage;
(3)调用shared_ptr构造函数
这里的执行顺序是什么呢?这里C++的做法与Java和C#就不一样了,他们总是执行相同的调用顺序,而这里C++的做
法似乎很"危险":它弹性很大,但是我们可以确定的是(2)肯定是在(3)之前被调用,原因很简单:因为(3)需要(2)产生的
对象,假设要是出现这样的调用顺序:(2)->(1)->(3),而在执行(1)的时候出现异常,那么导致了产生的PaintMessage
对象的指针丢失,那么该对象指针就不能被置入资源管理对象shared_ptr之中,现在我们面临的危险就已经很明显了:
调用processMessage时可能就发生资源泄露,哇靠,那怎么办呢?方法还是有的,这里主要的问题就是参数准备的时候
做了太多的步骤导致了由于调用顺序的问题引起了一系列的问题,那么我们可以通过分离语句达到减少函数调用之前
的准备事情的执行步骤数量,你可以这样调用,用单独的语句块内执行智能指针的构造过程:
std::tr1::shared_ptr<WindowsMesssage> sptrPaintMessage(new PaintMessage);
processMessage(sptrPaintMessage,messageProcedure);
由于编译器对"跨越语句块的各项操作"失去了执行重新排列的自由,所以编译器不能在它们之间任意选择执行顺序.

请记住:
■ 以独立语句将newed对象存储于(置入)智能指针内.如果不这样做,一旦异常被抛出,有可能导致难以察觉的资源
泄露.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: