从析构函数抛出异常的主要问题是,在调用析构函数的那一刻,另一个异常可能“正在运行”( std::uncaught_exception() == true
),因此在这种情况下该怎么做并不明显。用新异常“覆盖”旧异常将是处理这种情况的可能方法之一。但决定在这种情况下必须调用 std::terminate
(或另一个 std::terminate_handler
)。
C++11 通过 std::nested_exception
类引入了嵌套异常功能。此功能可用于解决上述问题。旧的(未捕获的)异常可以嵌套到新的异常中(反之亦然?),然后可以抛出嵌套的异常。但是这个想法没有被使用。 std::terminate
在 C++11 和 C++14 的这种情况下仍然被调用。
所以问题。是否考虑了嵌套异常的想法?有什么问题吗?在 C++17 中情况不会改变吗?
原文由 anton_rh 发布,翻译遵循 CC BY-SA 4.0 许可协议
您引用的问题发生在您的析构函数作为堆栈展开过程的一部分执行时(当您的对象不是作为堆栈展开的一部分创建时) 1 ,并且您的析构函数需要发出异常。
那么这是如何工作的呢?你有两个例外。异常
X
是导致堆栈展开的异常。异常Y
是析构函数想要抛出的异常。nested_exception
只能容纳 _其中一个_。所以也许你有例外
Y
包含 一个nested_exception
(或者可能只是一个exception_ptr
)。那么……您如何在catch
网站上处理这个问题?如果你捕捉到
Y
,并且它恰好嵌入了一些X
,你是如何得到它的?请记住:exception_ptr
是 _类型擦除的_;除了传递它,你唯一能做的就是重新抛出它。所以人们应该这样做:我没有看到很多人这样做。特别是因为会有非常多的可能的
X
-es。1 :请不要使用
std::uncaught_exception() == true
来检测这种情况。这是非常有缺陷的。