【发布时间】:2020-02-24 01:07:36
【问题描述】:
我了解到,如果在堆栈展开期间发生这种情况,如果抛出析构函数程序将中止,因为会传播超过 1 个异常。
这是一个带有注释的示例,可以证明这一点:
class Foo
{
public:
~Foo()
{
ReleaseResources();
}
private:
int* pInt;
void ReleaseResources()
{
if (!pInt)
throw 0;
else delete pInt;
}
};
int main() try
{
{
Foo local;
throw 1;
} // aborting here, because now 2 exceptions are propagating!
return 0;
}
catch (int& ex)
{
return ex;
}
但是我有一个类层次结构,其中一个析构函数调用一个可能抛出的函数,并且由于该条目层次结构被污染,这意味着现在所有析构函数都标记为noexcept(false)。
虽然编译器可以插入异常代码,但对于这些类的用户来说是不行的,因为如果发生上述代码示例的情况,它不会阻止程序中止。
因为我希望析构函数是异常安全的,所以我想到将它们全部标记为noexcept,但在析构函数中处理可能的异常,如下所示:
相同的示例,但经过重新设计,无法中止,并且析构函数异常安全:
class Foo
{
public:
~Foo() noexcept
{
try
{
ReleaseResources();
}
catch (int&)
{
// handle exception here
return;
}
}
private:
int* pInt;
void ReleaseResources()
{
if (!pInt)
throw 0;
else delete pInt;
}
};
int main() try
{
{
Foo local;
throw 1;
} // OK, not aborting here...
return 0;
}
catch (int& ex)
{
return ex;
}
问题是,这是处理析构函数内部异常的正常方法吗?有什么例子可以让这个设计出错吗?
主要目标是拥有异常安全的析构函数。
还有一个附带问题,在第二个示例中,在堆栈展开期间仍有 2 个异常在传播,如何调用不中止?如果在堆栈展开期间只允许一个异常?
【问题讨论】:
标签: c++ exception destructor