0

为什么这段代码不在类析构函数中调用 CloseHandles?
在我的代码测试中,我调用 '((MyClass*)pThis)->CloseHandles();' 明确地,但变量 m_bFinished 有错误的值。为什么 ?

#include <windows.h>
#include <异常>

我的班级
{
上市:

    显式 MyClass( void **pThis)
    {
        *p这=这;
        m_bFinished = 假;

        //这里代码打开句柄

        //发生错误
        throw new std::exception("抛出异常!");
    }

    〜我的班级()
    {
        if ( ! m_bFinished ) CloseHandles();
    }

    无效关闭句柄()
    {
        如果(m_bFinished)返回;

        //在这里关闭句柄。

        m_bFinished =真;
    }

私人的:
    bool m_bFinished;
};

int main(int argc, char* argv[])
{
    我的班级 * pMyClass;
    无效 * pThis = NULL;

    尝试
    {
        pMyClass = new MyClass(&pThis);
    }
    捕获(标准::异常 * e)
    {
        //删除pThis;

        如果 ( pThis )
        {
            ((MyClass*)pThis)->CloseHandles();
        }
    }

    返回0;
}
4

1 回答 1

3

因为类的析构函数在其构造函数抛出时不会运行 - 对象尚未完全初始化。

此外,您实际上不是在抛出std::exception,而是指向它的指针:

// dynamically allocates std::exception and throws a pointer to it
throw new std::exception("Exception thrown!");

编辑:我注意到你也在捕捉指针,所以这不是问题。但是,没有构造函数std::exception采用字符串文字,所以我想知道你的代码是如何编译的。

在任何情况下,如果在分配原始资源后构造函数可能会抛出,那么您就有潜在的泄漏。

您需要将资源包装在管理它的类中 - 可能是智能指针或类似的RAII包装器。并使用成员初始化列表

另一种选择是构造函数委托(C++11 中的新功能)。当一个对象的任何构造函数完成执行时,它就被认为是完全构造的。这意味着,如果从委托给另一个构造函数(您将在其中获取句柄)的构造函数抛出异常,则将调用析构函数。

用一些代码来说明:

struct Handle {
    Handle() : handle(new int()) {}
    ~Handle() { delete handle; }
    int* handle;
};

class MyClass {
    Handle h;
    MyFlass() : h() // handle initialized here
    {
       /**** code that may throw ****/
       // this will properly close handles because
       // the destructors of already initialized
       // members (like h) will be called
    }
    ~MyClass() { /* not called if constructor throws */ }
};

以及构造函数委托的示例:

#include <iostream>

class MyClass {
private:
    int* handle;
    MyClass(int)  // dummy parameter just for overloading
        : handle(new int()) { /* better not throw from here */ }
public:
    MyClass() : MyClass(0) // handle initialized here
    {
       /**** code that may throw ****/
       throw 42;
    }
    ~MyClass() { delete handle; std::cout << "dtor!"; }
};

int main()
{
    try { MyClass m; } catch (int) {};
}

输出是dtor!

于 2014-03-25T14:09:01.407 回答