从析构函数中引发异常的主要问题是,在调用析构函数的同时,另一个异常可能是“飞行中的”(std::uncaught_exception() == true
),因此在这种情况下该怎么办并不明显。用新异常“覆盖”旧异常将是处理这种情况的一种可能方法。但已决定在这种情况下必须调用std::terminate
(或另一个std::terminate_handler
)。
C ++ 11通过std::nested_exception
类引入了嵌套异常功能。此功能可用于解决上述问题。可以将旧的(未捕获的)异常嵌套到新的异常中(反之亦然?),然后可以抛出该嵌套的异常。但是这个想法没有被使用。std::terminate
在C ++ 11和C ++ 14中仍会在这种情况下调用它。
这样的问题。是否考虑过嵌套异常的想法?有什么问题吗?C ++ 17中的情况不会改变吗?
当析构函数作为堆栈展开过程的一部分执行时(当您的对象不是作为堆栈展开的一部分创建时)1,并且析构函数需要发出异常时,就会发生您引用的问题。
那怎么运作的呢?您有两个例外。X
导致堆栈释放的异常是例外。异常Y
是析构函数要抛出的异常。nested_exception
只能容纳其中一个。
因此,也许您有一个例外,其中Y
包含一个nested_exception
(或可能只是一个exception_ptr
)。那么...您如何在catch
现场处理呢?
如果您抓住了Y
它,并且它恰好嵌入X
了某些东西,您将如何获得它?请记住:exception_ptr
被类型擦除;除了传递它之外,您唯一可以做的就是将它扔掉。人们应该这样做:
catch(Y &e)
{
if(e.has_nested())
{
try
{
e.rethrow_nested();
}
catch(X &e2)
{
}
}
}
我没有看到很多人这样做。尤其是因为存在X
-es的可能性非常大。
1:请勿std::uncaught_exception() == true
用于检测这种情况。这是非常有缺陷的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句