gpt4 book ai didi

c++ - 类构造函数异常后清理数据

转载 作者:行者123 更新时间:2023-11-28 00:31:44 30 4
gpt4 key购买 nike

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

#include <windows.h>#include <exception>class MyClass{public:    explicit MyClass( void **pThis)    {        *pThis = this;        m_bFinished = false;        //code open handle here        //an error occurs        throw new std::exception("Exception thrown!");    }    ~MyClass()    {        if ( ! m_bFinished ) CloseHandles();    }    void CloseHandles()    {        if ( m_bFinished ) return;        //close handles here.        m_bFinished = true;    }private:    bool m_bFinished;};int main(int argc, char* argv[]){    MyClass * pMyClass;    void * pThis = NULL;    try    {        pMyClass = new MyClass(&pThis);    }    catch(std::exception * e)    {        //delete pThis;        if ( pThis )        {            ((MyClass*)pThis)->CloseHandles();        }    }    return 0;}

最佳答案

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

此外,您实际上并没有抛出 std::exception,而是一个指向它的指针:

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

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

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

您需要将资源包装在管理它的类中 - 可能是智能指针或类似的 RAII wrapper 。并使用 member initializer lists !

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

用一些代码来说明:

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 */ }
};

还有一个构造函数委托(delegate)的例子:

#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!

关于c++ - 类构造函数异常后清理数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22636975/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com