首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 基礎

C++ 析構函數完整指南

     編輯:C++ 基礎

核心使命:資源釋放的最後防線

建構函數負責「出生時初始化」,析構函數負責「死亡時清理」。它是特殊成員函數:

  • 名稱:~ClassName(~ 為位元補數運算子,此處為語法標記)。
  • 無參數、無回傳值、不可多載(一個類別僅能有一個)。
  • 無需手動呼叫,物件銷毀時自動觸發。
  • 若使用者未定義,編譯器合成預設析構函數(僅遞迴呼叫成員/基類析構)。

經典應用:動態記憶體管理(RAII 雛形)

class VLA { // Variable Length Array
public:
    VLA(int len);      // 建構:配置記憶體
    ~VLA();            // 析構:釋放記憶體
    void input();
    void show();
private:
    int* at(int i);
    const int m_len;
    int* m_arr;
    int* m_p;
};

VLA::VLA(int len) : m_len(len) {
    m_arr = (len > 0) ? new int[len] : nullptr;
}

VLA::~VLA() {
    delete[] m_arr;    // 關鍵:配置用 new[],釋放必用 delete[]
}

int main() {
    int n; cin >> n;
    VLA* arr = new VLA(n); // 堆上建立物件
    arr->input();
    arr->show();
    delete arr;            // 觸發 ~VLA(),釋放 m_arr
    return 0;
}

鐵律:new 配對 delete,new[] 配對 delete[]。析構函數確保「有配置必釋放」,避免記憶體洩漏。

析構時機與儲存區關係

物件類型儲存區析構觸發時機
全域/靜態物件全域資料區程式結束(main 返回後)
區域物件堆疊離開作用域(函數返回、區塊結束)
動態物件 (new)堆積呼叫 delete 時;未 delete 則不會析構

執行順序演示

#include <iostream>
#include <string>
using namespace std;

class Demo {
public:
    Demo(string s) : m_s(s) {}
    ~Demo() { cout << m_s << endl; }
private:
    string m_s;
};

Demo g_obj("2");  // 全域物件

void func() {
    Demo local("1"); // 區域物件
} // local 析構,輸出 1

int main() {
    Demo main_obj("3");       // 區域物件
    Demo* p = new Demo("4");  // 動態物件,未 delete
    func();
    cout << "main" << endl;   // 輸出 main
    return 0;
} // main_obj 析構輸出 3,g_obj 析構輸出 2
// p 指向的物件未 delete,~Demo() 未被呼叫

輸出順序:1 → main → 3 → 2。
區域物件按「後進先出」銷毀;全域物件在 main 結束後逆序銷毀;動態物件若無 delete 則永不析構(記憶體洩漏)。

new/delete 與建構/析構的綁定關係

C++ 保證:

  • new Type → 配置記憶體 → 呼叫建構函數。
  • delete ptr → 呼叫析構函數 → 釋放記憶體。

這是 C++ 相較 C 語言 malloc/free 的核心優勢:物件語意與記憶體管理綁定,RAII 機制的基石。

虛擬析構函數:多型刪除的必要條件

class Base { public: virtual ~Base() {} };
class Derived : public Base { /* ... */ };

Base* p = new Derived;
delete p; // 正確呼叫 Derived::~Derived() 再 Base::~Base()

若 Base 析構非虛擬,delete p 僅呼叫 Base::~Base(),導致 Derived 資源洩漏。基類若有虛擬函數,析構函數必須宣告為 virtual。

常見錯誤

  • ❌ 析構函數帶參數 / 重載 → 語法錯誤。
  • ❌ 手動呼叫 obj.~Class() → 僅在 placement new 等極少數場景合法,一般嚴禁。
  • ❌ 忘記 delete[] 陣列 → 未定義行為。
  • ❌ 基類析構非虛擬且透過基類指標刪除派生物件 → 資源洩漏。

總結

析構函數是 C++ 確定性資源管理的核心。遵循「誰配置、誰釋放、在析構函數中釋放」原則,配合 new/delete 配對使用,並為多型基類宣告虛擬析構,即能構建無洩漏、異常安全的 C++ 程式。

  1. 上一篇文章:
  2. 下一篇文章:
  • --热点文章
  • Copyright © 程式碼之家 All Rights Reserved