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

C++ delete 與內存洩露:虛析構函數的必要性

     編輯:C++ 入門

C++ 基類指針刪除派生對象:必須用虛析構函數

基類指針指向派生對象,delete 時若基類析構函數非虛,只會調用基類析構,導致派生類資源未釋放(內存洩露)。

問題演示

class A { public: ~A() { cout << "A dtor\n"; } };
class B : public A { public: ~B() { cout << "B dtor\n"; } };
int main() {
    A* p = new B();
    delete p; // 輸出:A dtor  (B dtor 未調用!)
}

原因

delete p 編譯期根據靜態類型 A* 決定調用 A::~A()。派生類析構函數不被調用,其中的 delete[]、fclose、unlock 等清理代碼全失效。

解決:虛析構函數

class A { public: virtual ~A() { cout << "A dtor\n"; } };
class B : public A { public: ~B() { cout << "B dtor\n"; } };
int main() {
    A* p = new B();
    delete p; // 輸出:B dtor → A dtor  (正確!)
}

機制

  • virtual ~A() 使析構函數成為虛函數,編入虛函數表
  • delete p 時編譯器生成代碼:查詢對象動態類型的虛表,調用對應析構函數
  • 派生類析構函數自動隱式虛,執行完後調用基類析構函數

最佳實踐

  1. 凡是作為基類、可能被繼承、且可能用基類指針刪除派生對象的類,析構函數必須聲明為 virtual
  2. 純虛析構函數也需提供定義(因派生類析構會調用它)
  3. 現代 C++ 推薦用智能指針(unique_ptr/shared_ptr)管理生命週期,避免手動 delete

補充:虛函數表開銷

每個含虛函數的類對象增加一個指針(vptr),每個類增加一張虛表。對於大量小對象可能有內存開銷,但正確性優先。

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