2013-10-28 36 views
5

我想弄清楚如何正確地清理我的對象在C++/CLI後。我該如何編寫適當的析構函數和終結器?

我已閱讀或脫脂這兩篇文章(onetwo)看着the standard,看着其他一些問題,特別是this one

我有各種信息:

  1. 終結應清理非託管資源(所以一切都被清理當對象被垃圾回收
  2. 析構函數應該清理託管資源(刪除FOO或Foo.Dispose()?),並調用(根據1
  3. 兩種析構函數終結器和終結器可以被多次調用(參見8.8.8的3第26頁端)
  4. 如果析構被稱爲終結器將不會被調用(根據1)(不是由CLR,也就是說,你仍然可以自己調用它)
  5. 析構函數將調用基類析構函數(請參閱3 p。 25)
  6. 有一個終結應該始終有一個析構函數的類(大概是爲了明確地清理非託管資源)
  7. 到終結,呼叫不會調用基類的終結(3 19.13.2第131頁)

但也有引起部分許多混亂的事實,

  1. 終結被稱爲析構函數在C#
  2. 析構函數內部生成Dispos e和finalize方法(不知道的Finalize),但Finalize方法不是終結
  3. 析構函數的語義是在C++ 不同和具有一般
兩個確定性清理UND垃圾收集的複雜性

我想作爲一個答案是一個類的例子,它可能包含所有不同類型的數據(託管,非託管,託管但是一次性的,任何你能想到的)以及正確書寫的析構函數和終結器。

我有兩個更具體的問題:

  1. 難道是接受處理的通過只是有一個bool hasBeenCleanedUp成員,使整個代碼在析構函數/終結條件上被多次調用的可能性?
  2. 什麼樣的數據只能由析構函數清理,但不能在終結器中清理,因爲它可能已被gc清除了?
+0

如果*你*給出了不同種類的數據的例子,並告訴我們你的嘗試,那麼你會得到更好的迴應,然後我們可以給出反饋。 –

回答

4

不是您的問題的完整答案,但太長,不適合評論。

全面管理世界,其中每個對象只管理對象的引用,沒有必要對終結或析構函數,因爲唯一的資源就是內存GC需要它照顧。

當您引用非託管資源你必須釋放他們當你不再需要它們的責任。

因此您需要實施專用清理代碼

有兩個可能性:

  • 你知道,當你不需要的非託管資源了,所以你可以確定性運行清理代碼,這是通過析構函數來實現/處置​​

  • 你不知道什麼時候這些資源不再需要了,所以你推遲清理在最後可能的時刻,當包裹資源的對象CES是由GC回收,這是通過終結實施

你想這是更好的是在第一種情況下,因爲你不消耗比你需要更多的內存和你避免一些額外開銷GC過程。

您通常都會實現這兩個功能,因爲實例的生命週期可能因使用情況而異。

CLR級別沒有確定性清理,只有終結器。

語言/ API級別有確定性清理的支持:在++你有退出的範圍,或者當「刪除」

  • 時調用析構函數無論是原生的C

    • .Net世界中您有Dispose模式

    • 在純託管的C++/CLI世界中,析構函數映射到Dispose

    當你必須知道什麼時候可以運行調用清理代碼(或讓基礎設施的呼叫)的析構函數的機會。一旦清理完成,您可以擺脫所有的終結過程,以便可以在下一個GC中立即收集該對象。

    關於你的第一個系列的點一些澄清:

    1. 析構函數負責非託管資源過多的清理;它可以調用終結器,如果它是你分解清理代碼的地方。

    2. 他們在技術上可以,但在邏輯上應防止它用一個簡單的布爾防衛

    3. 是因爲所有的清理工作應該做的,所以你問CLR沒有最終確定對象

    4. 是因爲基類知道它已分配的資源

    5. 是的,這是確定的清理

    6. 你應該確保它的情況下

    而且別人:

    1. 是〜MyClass的映射到定案方法

    2. 正如上面說的析構函數映射到處置的覆蓋,但您應該自己實現終結器:!MyClass

    3. 摘要:C++析構函數和Dispose模式用於確定性清理,C#析構函數, C++/CLI終結器用於由GC觸發的非確定性清除。

  • 相關問題