因为类的析构函数在其构造函数抛出时不会运行 - 对象尚未完全初始化。
此外,您实际上不是在抛出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!
。