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

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

2013年08月23日 ⁄ 综合 ⁄ 共 1405字 ⁄ 字号 评论关闭

条款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对象存储于(置入)智能指针内.如果不这样做,一旦异常被抛出,有可能导致难以察觉的资源
泄露.

抱歉!评论已关闭.