析構函數又稱終結器,用於析構類的實例。 定義 析構函數(destructor) 與構造函數相反,當對象結束其生命周期時(例如對象所在的函數已調用完畢),系統自動執行析構函數。析構函數往往用來做“清理善後” 的工作(例如在建立對象時用new開闢了一片記憶體空間,delete會自動調用析構函數後釋放記憶體) ...
析構函數又稱終結器,用於析構類的實例。
定義
析構函數(destructor) 與構造函數相反,當對象結束其生命周期時(例如對象所在的函數已調用完畢),系統自動執行析構函數。析構函數往往用來做“清理善後” 的工作(例如在建立對象時用new開闢了一片記憶體空間,delete會自動調用析構函數後釋放記憶體)。
析構函數簡介
以C++語言為例:[1] 析構函數名也應與類名相同,只是在函數名前面加一個位取反符~,例如~stud( ),以區別於構造函數。它不能帶任何參數,也沒有返回值(包括void類型)。只能有一個析構函數,不能重載。如果用戶沒有編寫析構函數,編譯系統會自動生成一個預設的析構函數(即使自定義了析構函數,編譯器也總是會為我們合成一個析構函數,並且如果自定義了析構函數,編譯器在執行時會先調用自定義的析構函數再調用合成的析構函數),它也不進行任何操作。所以許多簡單的類中沒有用顯式的析構函數。析構函數的使用
-
不能在結構中定義析構函數。只能對類使用析構函數。
-
一個類只能有一個析構函數。
-
無法繼承或重載析構函數。
-
無法調用析構函數。它們是被自動調用的。
-
析構函數既沒有修飾符,也沒有參數。
聲明:
class Car { ~ Car() // destructor { // cleanup statements... } }
該析構函數隱式地對對象的基類調用 Finalize。這樣,前面的析構函數代碼被隱式地轉換為:
protected override void Finalize() { try { // cleanup statements... } finally { base.Finalize(); } }
這意味著對繼承鏈中的所有實例遞歸地調用 Finalize 方法(從派生程度最大的到派生程度最小的)。
註意 |
---|
不應使用空析構函數。如果類包含析構函數,Finalize 隊列中則會創建一個項。調用析構函數時,將調用垃圾回收器來處理該隊列。如果析構函數為空,則只會導致不必要的性能丟失。 |
程式員無法控制何時調用析構函數,因為這是由垃圾回收器決定的。垃圾回收器檢查是否存在應用程式不再使用的對象。如果垃圾回收器認為某個對象符合析構,則調用析構函數(如果有)並回收用來存儲此對象的記憶體。程式退出時也會調用析構函數。
可以通過調用 Collect 強制進行垃圾回收,但大多數情況下應避免這樣做,因為這樣會導致性能問題有關更多信息,請參見強制垃圾回收。
使用析構函數釋放資源
通常,與運行時不進行垃圾回收的編程語言相比,C# 無需太多的記憶體管理。這是因為 .NET Framework 垃圾回收器會隱式地管理對象的記憶體分配和釋放。但是,當應用程式封裝視窗、文件和網路連接這類非托管資源時,應當使用析構函數釋放這些資源。當對象符合析構時,垃圾回收器將運行對象的 Finalize 方法。
資源的顯式釋放
如果您的應用程式在使用昂貴的外部資源,則還建議您提供一種在垃圾回收器釋放對象前顯式地釋放資源的方式。可通過實現來自 IDisposable 介面的 Dispose 方法來完成這一點,該方法為對象執行必要的清理。這樣可大大提高應用程式的性能。即使有這種對資源的顯式控制,析構函數也是一種保護措施,可用來在對 Dispose 方法的調用失敗時清理資源。
示例
下麵的示例創建三個類,這三個類構成了一個繼承鏈。類 First 是基類,Second 是從 First 派生的,而 Third 是從 Second 派生的。這三個類都有析構函數。在 Main() 中,創建了派生程度最大的類的實例。註意:程式運行時,這三個類的析構函數將自動被調用,並且是按照從派生程度最大的到派生程度最小的次序調用。
class First { ~First() { System.Console.WriteLine("First's destructor is called"); } } class Second: First { ~Second() { System.Console.WriteLine("Second's destructor is called"); } } class Third: Second { ~Third() { System.Console.WriteLine("Third's destructor is called"); } } class TestDestructors { static void Main() { Third t = new Third(); } }