C++核心準(zhǔn)則C.36:析構(gòu)函數(shù)不應(yīng)該失敗

Reason(原因)
In general we do not know how to write error-free code if a destructor should fail. The standard library requires that all classes it deals with have destructors that do not exit by throwing.
如果析構(gòu)函數(shù)會(huì)失敗,通常我們也不知道怎么寫出沒有錯(cuò)誤的代碼。標(biāo)準(zhǔn)庫(kù)要求它處理所有的類的析構(gòu)函數(shù)都不要拋出異常。
class X {public:
?? ~X() noexcept;
?? // ...
};
X::~X() noexcept {
?? // ...
?? if (cannot_release_a_resource) terminate();
?? // ...
}
左右滑動(dòng)查看更多

Many have tried to devise a fool-proof scheme for dealing with failure in destructors. None have succeeded to come up with a general scheme. This can be a real practical problem: For example, what about a socket that won't close? The writer of a destructor does not know why the destructor is called and cannot "refuse to act" by throwing an exception. See discussion. To make the problem worse, many "close/release" operations are not retryable. If at all possible, consider failure to close/cleanup a fundamental design error and terminate.
為了發(fā)明處理析構(gòu)函數(shù)中的錯(cuò)誤的可靠方法,人們已經(jīng)進(jìn)行了各種嘗試。沒有任何一種方法發(fā)展成通用的做法。這是一個(gè)真正的實(shí)踐性問題:例如,socket不能關(guān)閉時(shí)怎么辦?析構(gòu)函數(shù)的編寫者不知道析構(gòu)函數(shù)因?yàn)槭裁幢徽{(diào)用,而且不能通過拋出異常來(lái)拒絕這個(gè)動(dòng)作。參見討論(https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Sd-never-fail)。更為嚴(yán)重的是,很多“關(guān)閉/釋放"操作是不可重試的。如果可能的話,將關(guān)閉/釋放時(shí)發(fā)生的錯(cuò)誤當(dāng)作基本的設(shè)計(jì)錯(cuò)誤并終止執(zhí)行。?

Declare a destructor noexcept. That will ensure that it either completes normally or terminate the program.
將析構(gòu)函數(shù)定義為noexcept。這將保證要么正常結(jié)束析構(gòu),要么終止程序。

If a resource cannot be released and the program may not fail, try to signal the failure to the rest of the system somehow (maybe even by modifying some global state and hope something will notice and be able to take care of the problem). Be fully aware that this technique is special-purpose and error-prone. Consider the "my connection will not close" example. Probably there is a problem at the other end of the connection and only a piece of code responsible for both ends of the connection can properly handle the problem. The destructor could send a message (somehow) to the responsible part of the system, consider that to have closed the connection, and return normally.
如果資源不能被釋放而且程序有可能不失敗,以某種方式(甚至可以是修改某些全局變量并寄希望于某些程序會(huì)注意并處理該問題)向程序的其他部分發(fā)出錯(cuò)誤信號(hào)。需要充分意識(shí)到這個(gè)技術(shù)的特殊目的,而且容易發(fā)生錯(cuò)誤。考慮示例“我的鏈接不會(huì)關(guān)閉"。有可能在連接的另一端存在問題,而且對(duì)于鏈接的兩端來(lái)說,只存在一段代碼負(fù)有正確地處理這個(gè)問題的責(zé)任。析構(gòu)函數(shù)可以(以某種方式)向系統(tǒng)中負(fù)責(zé)處理錯(cuò)誤的部分發(fā)送一條消息,同時(shí)認(rèn)為我們已經(jīng)關(guān)閉了鏈接并正確的返回了。

If a destructor uses operations that may fail, it can catch exceptions and in some cases still complete successfully (e.g., by using a different clean-up mechanism from the one that threw an exception).
如果析構(gòu)函數(shù)使用了可能失敗的操作,它可以自己捕捉異常并且在有些情況下依然成功地結(jié)束(例如使用拋出異常之外的不同的清除機(jī)制)。

(Simple) A destructor should be declared noexcept if it could throw.
(簡(jiǎn)單)如果可能拋出異常,那么析構(gòu)函數(shù)應(yīng)該聲明為noexcept。

譯者注:聲明noexcept,編譯器就不會(huì)生成異常的傳遞機(jī)制,這時(shí)一旦拋出異常,程序會(huì)直接中止。


https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c36-a-destructor-may-not-fail
覺得本文有幫助?請(qǐng)分享給更多人。
關(guān)注【面向?qū)ο笏伎肌枯p松學(xué)習(xí)每一天!
面向?qū)ο箝_發(fā),面向?qū)ο笏伎迹?/span>
