我運行了一個示例程序,確實調用了堆棧分配對象的析構函數,但這是由標準保證的嗎?在C++中拋出後調用析構函數嗎?
回答
是,它是保證(提供的異常被捕獲),下降到其中析構函數調用的順序:
C++ 11 15.2構造和析構[except.ctor]
1控件從throw表達式傳遞到處理函數時,自從try塊被輸入後構造的所有自動對象都會調用析構函數。 自動對象按照其構造完成 的相反順序銷燬。
此外,如果異常對象施工過程中引發,所述部分構造的對象的子對象,保證被正確地破壞:
2的任何存儲持續時間,其初始化或 破壞的目的被一個異常終止,將會爲其所有完全構造的子對象(不包括 聯合類類的變體成員)執行析構函數 ,也就是說,對於主體構造函數(12.6.2)已完成執行的 子對象和 析構函數尚未開始執行。同樣,如果對象的非委託構造函數已完成執行,並且此對象的委託構造函數退出且出現異常,則將調用對象的析構函數。如果對象是以 新表達式分配的,則會調用匹配的釋放函數(3.7.4.2,5.3.4, 12.5)以釋放對象佔用的存儲空間(如果有)。
這整個過程被稱爲「堆棧展開」:
3要求自動對象析構函數的方法,構造從try塊到一拋表達的路徑上 被稱爲「堆 展開「。如果在堆棧展開過程中調用的析構函數以 作爲異常退出,則調用std :: terminate(15.5.1)。
堆疊展開形成了廣泛使用的技術Resource Acquisition Is Initialization (RAII)的基礎。
請注意,如果未捕獲到異常,堆棧展開不一定會完成。在這種情況下,堆棧展開是否完成取決於實現。但是,無論堆疊展開是否完成,在這種情況下,您都可以保證最終致電std::terminate
。
C++ 11 15.5.1的std ::終止()函數[except.terminate]
2…在沒有找到匹配處理程序的情況下, 它是實現定義的,無論在調用
std::terminate()
之前堆棧是否展開。
注意:關於構造中斷的對象。對象本身並沒有被銷燬(它從來沒有真正存在過),保證的是到目前爲止完全構造的子部件(基類,屬性)將以相反的順序銷燬。 –
爲未捕獲的異常添加了有關堆棧展開(或不展開)的信息。 –
- 1. 從JNI函數拋出java異常之後調用C++析構函數嗎?
- 2. new []/delete []並在C++中拋出構造函數/析構函數
- 3. 調用可以在C++中拋出異常的函數的析構函數
- 4. 構造函數拋出異常後可以調用finalize嗎?
- 5. 在構造函數中拋出的異常:析構函數是否被調用?
- 6. 在C++中調用析構函數
- 7. 如果對象在構造函數中拋出異常,基類的析構函數會調用嗎?
- 8. 文件流析構函數可以在C++中拋出異常嗎?
- 9. C#析構函數超出範圍後不會調用
- 10. 成功調用析構函數或調用empy析構函數後出現Seg錯誤。 C++
- 11. C++中的析構函數調用
- 12. 奇怪析構函數調用在C++
- 13. 空std :: list當析構函數被調用時拋出異常
- 14. C++使用與析構函數RAII拋出
- 15. C++:從析構函數中拋出異常
- 16. C++從析構函數中拋出異常
- 17. C#:'拋出'退出當前函數嗎?
- 18. std :: remove_if調用析構函數嗎?
- 19. 在析構函數中調用成員函數後的構造函數
- 20. Visual C#中沒有析構函數嗎?
- 21. Java中有C++析構函數嗎?
- 22. 運行析構函數,當構造函數拋出異常
- 23. 拋出異常然後調用構造函數?
- 24. C++:析構函數在超出範圍之前被調用?
- 25. 正在從析構函數調用非成員函數嗎?
- 26. C++析構函數沒有被調用?
- 27. C++析構函數早期調用
- 28. C++意外的析構函數調用
- 29. C++析構函數太早調用
- 30. 在C++中,構造函數和析構函數可以是內聯函數嗎?
當然可以。 [RAII](http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization)是C++中最重要的成語之一,取決於此。 – Jon
是的,這是異常處理的重點。 –