C++分析如何用虛析構與純虛析構處理內存泄漏
一、問題引入
使用多態時,如果有一些子類的成員開辟在堆區,那麼在父類執行完畢釋放後,沒有辦法去釋放子類的內存,這樣會導致內存的泄漏。如下代碼段。
如果沒有堆區的數據,可以不寫虛析構或純虛析構。
#include <iostream> #include <string> using namespace std; class Animal{ public: Animal(){ cout<<"Animal-構造"<<endl; } ~Animal(){ cout<<"Animal-析構"<<endl; } virtual void Run()=0; //純虛函數無需實現,隻需聲明 }; class Cat:public Animal{ public: string *s_name; Cat(string name){ s_name = new string(name);//在堆區創建內存 cout<<"Cat-構造"<<endl; } void Run() { cout<<*s_name<<"->"<<"Cat-Run"<<endl; } ~Cat(){ cout<<"Cat-析構"<<endl; if(s_name!=NULL){ delete s_name; s_name=NULL; } } }; int main() { Animal *a; a = new Cat("Tom"); a->Run(); delete a; //父類指針析構的時候,不會調用子類析構函數 return 0; }
運行結果:
結果可以看到都有父類和子類的構造,雖然在主函數中delete 父類,但最終隻有父類的析構函數,此時子類在堆區創建的s_name並沒有得到釋放,導致內存泄漏。
以上的問題我們引入虛析構和純虛析構來解決——父類指針釋放子類對象時不幹凈的問題
二、利用虛析構解決
虛析構隻需要在析構函數前加關鍵字 virrtual 即可,再觀察結果,可以看到父類和子類的都執行瞭析構函數,而子類中在堆區創建的數據也被釋放幹凈,這是最終的結果!
virtual ~Animal(){ cout<<"Animal析構"<<endl; }
三、利用純虛析構解決
純虛析構格式如下,和純虛函數有點類似,但需要有具體的聲明和具體的實現。純虛析構需要在類外實現.
class Animal{ public: Animal(){ cout<<"Animal-構造"<<endl; } //虛析構 /*virtual ~Animal(){ cout<<"Animal析構"<<endl; }*/ //純虛析構 virtual ~Animal()=0; virtual void Run()=0; //純虛函數無需實現,隻需聲明 }; //需要有聲明,也需要有實現 Animal::~Animal(){ cout<<"純虛析構"<<endl; }
結果如下,和虛析構有相同的作用
四、總結
虛析構和純虛析構
相同點: 都可以解決父類指針釋放子類對象,都需要有具體的實現
不同點: 純虛析構屬於抽象類,無法實例化對象
到此這篇關於C++分析如何用虛析構與純虛析構處理內存泄漏的文章就介紹到這瞭,更多相關C++內存泄漏內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!