2013-04-11 44 views
1

這是一個面試問題。 我告訴他,如果堆棧展開已經在進行中,那麼程序可能會終止。除此之外,如果正確處理異常,您會發現任何問題。 只要處理得當,我就告訴過他。但他對我的迴應並不滿意。C++:從析構函數中拋出異常

+1

預期的答案可能是:「不要這樣做」。在這裏閱讀更多:http://stackoverflow.com/questions/130117/throwing-exceptions-out-of-a-destructor – Misch 2013-04-11 14:24:08

+0

如果你的類被破壞,因爲拋出異常,並且棧正在展開,並且析構函數拋出一個例外,該程序將立即終止。沒有辦法來捕捉或處理這樣的例外。 – Wug 2013-04-11 14:29:06

+1

當你嘗試建立回答你所做的事情的理由時,你可能應該已經澄清了你的回答,相對於在析構函數中拋出一個析構函數與*的異常。 – WhozCraig 2013-04-11 14:34:57

回答

3

那麼,你無法知道是否已經有一個活動異常。如果存在,如果讓另一個異常從析構函數中轉義,則程序將終止。

因此我真的不按照你的說法:

我告訴他沒有,只要它被妥善處理。

你怎麼能「正確地處理」它,而不是讓它從第一個地方逃離析構函數?如果我是面試官,那將是我的下一個問題。

0

如果你從中拋出析構函數,這意味着該異常實際上是離開析構函數。所以妥善處理部分是不可能的:你無法知道它將如何處理。

還有一個額外的細微問題:在很多非平凡的情況下,編寫異常安全的代碼是不可能的(或者至少是非常昂貴的),除非析構函數被假定爲不拋出。如果你的析構函數拋出,你的類的用戶將無法用它編寫好的代碼。例如:除非它所包含的對象的析構函數保證不會拋出,否則不可能爲容器編寫一個異常安全的析構函數。將不會有terminate()的調用,但容器析構函數會泄漏資源。

0

從析構器投擲使沒有意義

關於析構函數中唯一可恢復的錯誤類型是在關閉/刷新文件(或類似網絡錯誤等)時發生I/O錯誤。但是從這些情況中恢復是微不足道的。只需報告錯誤並繼續。無論如何你並不需要這個文件,你只是試圖關閉它!放棄你所做的任何事情是很浪費的,因爲你甚至不需要一個文件中的錯誤。

析構函數中可能發生的所有其他類型的失敗,例如無法解鎖互斥鎖或釋放一塊內存,可能無法恢復並且保證可致電terminate()

另一方面,由於計算無法繼續,所以在計算中分配資源或未能執行某些I/O操作時發生錯誤,將導致拋出。但是這不應該發生在析構函數中,或者如果它發生了,它應該在析構函數中處理(爲什麼?再次,讓它傳播離開是沒有意義的,這不會阻止錯誤將放棄計算可以愉快地繼續)。

因此,即使從析構函數中拋出完全安全和明確的,它也不會過多地購買我們。