問題描述
從析構(gòu)函數(shù)拋出異常的主要問題是,在調(diào)用析構(gòu)函數(shù)的那一刻,另一個異常可能是飛行中"(std::uncaught_exception() == true
),所以它是在這種情況下該怎么做并不明顯.用新的覆蓋"舊的例外將是處理這種情況的可能方法之一.但決定在這種情況下必須調(diào)用 std::terminate
(或另一個 std::terminate_handler
).
The main problem with throwing exceptions from destructor is that in the moment when destructor is called another exception may be "in flight" (std::uncaught_exception() == true
) and so it is not obvious what to do in that case. "Overwriting" the old exception with the new one would be the one of the possible ways to handle this situation. But it was decided that std::terminate
(or another std::terminate_handler
) must be called in such cases.
C++11 通過 std::nested_exception
類引入了嵌套異常功能.此功能可用于解決上述問題.舊的(未捕獲的)異常可以嵌套到新的異常中(反之亦然?),然后可以拋出嵌套的異常.但是這個想法沒有被使用.std::terminate
在 C++11 和 C++14 中仍然會在這種情況下被調(diào)用.
C++11 introduced nested exceptions feature via std::nested_exception
class. This feature could be used to solve the problem described above. The old (uncaught) exception could be just nested into the new exception (or vice versa?) and then that nested exception could be thrown. But this idea was not used. std::terminate
is still called in such situation in C++11 and C++14.
所以問題.是否考慮了嵌套異常的想法?它有什么問題嗎?C++17不會改變這種情況嗎?
So the questions. Was the idea with nested exceptions considered? Are there any problems with it? Isn't the situation going to be changed in the C++17?
推薦答案
當(dāng)您的析構(gòu)函數(shù)作為堆棧展開過程的一部分執(zhí)行時(當(dāng)您的對象不是作為堆棧展開的一部分創(chuàng)建時),您引用的問題就會發(fā)生1,并且您的析構(gòu)函數(shù)需要發(fā)出異常.
The problem you cite happens when your destructor is being executed as part of the stack unwinding process (when your object was not created as part of stack unwinding)1, and your destructor needs to emit an exception.
那么它是如何工作的呢?你有兩個例外.異常 X
是導(dǎo)致堆棧展開的異常.異常 Y
是析構(gòu)函數(shù)想要拋出的異常.nested_exception
只能容納一個.
So how does that work? You have two exceptions in play. Exception X
is the one that's causing the stack to unwind. Exception Y
is the one that the destructor wants to throw. nested_exception
can only hold one of them.
所以也許你有異常 Y
contain 一個 nested_exception
(或者可能只是一個 exception_ptr
).那么...你如何在 catch
站點處理這個問題?
So maybe you have exception Y
contain a nested_exception
(or maybe just an exception_ptr
). So... how do you deal with that at the catch
site?
如果你捕捉到Y
,并且它恰好有一些嵌入的X
,你怎么得到它?記住:exception_ptr
是類型擦除;除了傳遞它之外,你唯一能做的就是重新扔掉它.所以人們應(yīng)該這樣做嗎:
If you catch Y
, and it happens to have some embedded X
, how do you get it? Remember: exception_ptr
is type-erased; aside from passing it around, the only thing you can do with it is rethrow it. So should people be doing this:
catch(Y &e)
{
if(e.has_nested())
{
try
{
e.rethrow_nested();
}
catch(X &e2)
{
}
}
}
我沒有看到很多人這樣做.尤其是因為可能存在大量的 X
-es.
I don't see a lot of people doing that. Especially since there would be an exceedingly large number of possible X
-es.
1:請不要使用 std::uncaught_exception() == true
來檢測這種情況.這是非常有缺陷的.
1: Please do not use std::uncaught_exception() == true
to detect this case. It is extremely flawed.
這篇關(guān)于為什么 C++ 不使用 std::nested_exception 來允許從析構(gòu)函數(shù)拋出?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!