詳解C++中的析構(gòu)函數(shù)
簡(jiǎn)介
析構(gòu)函數(shù)(Destructors),是對(duì)象的成員函數(shù),沒有返回值也沒有參數(shù),且一個(gè)類只有一個(gè)析構(gòu)函數(shù),當(dāng)對(duì)象被銷毀的時(shí)候調(diào)用,被銷毀通常有這么幾個(gè)情況。
- 函數(shù)執(zhí)行結(jié)束
- 程序執(zhí)行結(jié)束
- 程序塊包含的局部變量
- delete操作
什么時(shí)候要自己寫析構(gòu)函數(shù)?
編譯器會(huì)自動(dòng)創(chuàng)建默認(rèn)的析構(gòu)函數(shù),通常都沒有問題,但是當(dāng)我們?cè)陬愔袆?dòng)態(tài)分配了內(nèi)存空間時(shí),我們需要手段的回收這塊空間,防止內(nèi)存溢出。就像這樣
class String
{
private:
char *s;
int size;
public:
String(char *); // constructor
~String(); // destructor
};
String::String(char *c)
{
size = strlen(c);
s = new char[size+1];
strcpy(s,c);
}
String::~String()
{
delete []s;
}
私有的析構(gòu)函數(shù)
可以將析構(gòu)函數(shù)的訪問權(quán)限設(shè)置為private,設(shè)置時(shí)沒有問題的,但是一個(gè)問題就是,通常的手段就沒法調(diào)用析構(gòu)函數(shù)了。
如下所示,程序結(jié)束后要調(diào)用析構(gòu)函數(shù),但是析構(gòu)函數(shù)時(shí)私有的沒法調(diào)用,所以會(huì)編譯出錯(cuò)。
#include <iostream>
using namespace std;
class Test {
private:
~Test() {}
};
int main()
{
Test t;
}
以下這樣不會(huì)有問題,因?yàn)闆]有對(duì)象被建立,也不用析構(gòu)
int main()
{
Test* t;
}
以下這樣也不會(huì)有問題,因?yàn)閯?dòng)態(tài)分配的內(nèi)存需要程序員手段釋放,所以程序結(jié)束時(shí)沒有釋放內(nèi)存,也沒有調(diào)用析構(gòu)函數(shù)。這里插一句,動(dòng)態(tài)分配的內(nèi)存如果不手動(dòng)釋放,程序結(jié)束后也會(huì)不會(huì)釋放,但是現(xiàn)代操作系統(tǒng)可以幫我們釋放,因?yàn)檫@個(gè)動(dòng)態(tài)分配的內(nèi)存和這個(gè)進(jìn)程有關(guān),操作系統(tǒng)應(yīng)該可以捕獲到這個(gè)泄露的內(nèi)存從而釋放。(查資料看到的)
int main()
{
Test* t = new Test;
}
如果使用delete來(lái)刪除對(duì)象,會(huì)編譯出錯(cuò)
int main()
{
Test* t = new Test;
delete t;//編譯出錯(cuò),無(wú)法調(diào)用私有的析構(gòu)函數(shù)
}
可以利用Friend函數(shù),進(jìn)行對(duì)象的銷毀,因?yàn)镕riend可以訪問私有成員,所以可以訪問析構(gòu)函數(shù)。
#include <iostream>
class Test {
private:
~Test() {}
friend void destructTest(Test*);
};
void destructTest(Test* ptr)
{
delete ptr;
}
int main()
{
Test* ptr = new Test;
destructTest(ptr);
return 0;
}
或者給類寫一個(gè)銷毀的方法,在需要銷毀的時(shí)候調(diào)用。
class Test {
public:
destroy(){delete this};
private:
~Test() {}
};
那么什么時(shí)候需要使用私有的析構(gòu)函數(shù)呢?當(dāng)我們只希望動(dòng)態(tài)分配對(duì)象空間(在堆上)時(shí)候,用私有析構(gòu),就防止了在棧上分配,因?yàn)樵诰幾g階段就會(huì)出錯(cuò)。
虛析構(gòu)函數(shù)
當(dāng)類用到多態(tài)的特性時(shí)候,使用虛析構(gòu)函數(shù)??慈缦碌睦?。
#include <iostream>
using namespace std;
class Base
{
public:
Base(){
cout << "Base Constructor Called\n";
}
~Base(){
cout << "Base Destructor called\n";
}
};
class Derived1: public Base
{
public:
Derived1(){
cout << "Derived constructor called\n";
}
~Derived1(){
cout << "Derived destructor called\n";
}
};
int main()
{
Base *b = new Derived1();
delete b;
}
例子里的析構(gòu)函數(shù)都不是虛函數(shù),當(dāng)我們想用基類的指針來(lái)刪除派生類對(duì)象的時(shí)候,就出現(xiàn)了問題,“undefined behavior”,c++標(biāo)準(zhǔn)里規(guī)定,只由編譯器實(shí)現(xiàn),通常這時(shí)不會(huì)報(bào)錯(cuò),會(huì)調(diào)用基類的析構(gòu)函數(shù)。但這應(yīng)該不是我們想要的,這會(huì)導(dǎo)致內(nèi)存泄漏。所以要把析構(gòu)函數(shù)置為虛函數(shù)。(msvc似乎不用給析構(gòu)函數(shù)加virtual,默認(rèn)就是虛的,gcc沒有默認(rèn)還是要加的)
另外虛析構(gòu)函數(shù)可以是純虛析構(gòu)函數(shù),但是要提供函數(shù)體,不然沒法析構(gòu),因?yàn)樘撐鰳?gòu)函數(shù)和一般的虛函數(shù)的overide還不一樣,虛析構(gòu)函數(shù)要挨個(gè)執(zhí)行,不提供函數(shù)體,會(huì)編譯出錯(cuò)。
析構(gòu)函數(shù)的執(zhí)行順序
派生類,成員對(duì)象,基類這樣
class B
{public: virtual ~B(){cout<<"基類B執(zhí)行了"<<endl; }
};
class D
{public:virtual ~D(){cout<<"成員D執(zhí)行了"<<endl; }
} ;
class E
{public:virtual ~E(){cout<<"成員E執(zhí)行了"<<endl; }
} ;
class A
{public:virtual ~A(){cout<<"基類A執(zhí)行了"<<endl;};
};
class C:public A,B
{
public:virtual ~C(){cout<<"派生類執(zhí)行了"<<endl;};
private:
E e;
D d;
};
int main()
{
C *c;
c=new C();
delete c;
}
結(jié)果為
派生類執(zhí)行了
成員D執(zhí)行了
成員E執(zhí)行了
基類B執(zhí)行了
基類A執(zhí)行了
參考
[1]什么時(shí)候使用虛函數(shù)https://stackoverflow.com/questions/461203/when-to-use-virtual-destructors
[2]析構(gòu)函數(shù)https://www.geeksforgeeks.org/destructors-c/
[3]虛析構(gòu)函數(shù)https://www.geeksforgeeks.org/virtual-destructor/
[4]純析構(gòu)函數(shù)https://www.geeksforgeeks.org/pure-virtual-destructor-c/
以上就是詳解C++中的析構(gòu)函數(shù)的詳細(xì)內(nèi)容,更多關(guān)于C++ 析構(gòu)函數(shù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- C++超詳細(xì)講解構(gòu)造函數(shù)與析構(gòu)函數(shù)的用法及實(shí)現(xiàn)
- C++分析類的對(duì)象作類成員調(diào)用構(gòu)造與析構(gòu)函數(shù)及靜態(tài)成員
- C++深入講解對(duì)象的銷毀之析構(gòu)函數(shù)
- C++編程析構(gòu)函數(shù)拷貝構(gòu)造函數(shù)使用示例詳解
- C++中構(gòu)造函數(shù)與析構(gòu)函數(shù)的詳解及其作用介紹
- C++踩坑實(shí)戰(zhàn)之構(gòu)造和析構(gòu)函數(shù)
- 正確理解C++的構(gòu)造函數(shù)和析構(gòu)函數(shù)
- C++ virtual destructor虛擬析構(gòu)函數(shù)
- C++超詳細(xì)講解析構(gòu)函數(shù)
相關(guān)文章
C/C++連接MySQL數(shù)據(jù)庫(kù)詳細(xì)圖文教程
在實(shí)際開發(fā)中我們經(jīng)常需要對(duì)數(shù)據(jù)庫(kù)進(jìn)行訪問,下面這篇文章主要介紹了C/C++連接MySQL數(shù)據(jù)庫(kù)的詳細(xì)圖文教程,文中通過代碼以及圖文介紹是非常詳細(xì),需要的朋友可以參考下2024-01-01
C語(yǔ)言進(jìn)階教程之字符函數(shù)和字符串函數(shù)
C語(yǔ)言中對(duì)字符和字符串的處理很是頻繁,但是C語(yǔ)言本身是沒有字符串類型的,字符串通常放在常量字符串中或者字符數(shù)組中,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言進(jìn)階教程之字符函數(shù)和字符串函數(shù)的相關(guān)資料,需要的朋友可以參考下2022-11-11
探討:用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列(我作為面試官的小結(jié))
作為面試官的我,經(jīng)常拿這道用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列的面試題來(lái)考面試者,通過對(duì)面試者的表現(xiàn)和反應(yīng),有一些統(tǒng)計(jì)和感受,在此做個(gè)小結(jié)2013-05-05
C++ 中malloc()和free()函數(shù)的理解
這篇文章主要介紹了C++ 中malloc()和free()函數(shù)的理解的相關(guān)資料,這里提供用法示例幫助大家理解這部分知識(shí),需要的朋友可以參考下2017-08-08
c語(yǔ)言swap(a,b)值交換的4種實(shí)現(xiàn)方法
c語(yǔ)言swap(a,b)值交換的4種實(shí)現(xiàn)方法,這么好的東西,盡管簡(jiǎn)單,但值得發(fā)表,以此共享。2013-02-02
C++使用LibCurl實(shí)現(xiàn)Web隱藏目錄掃描功能
LibCurl是一個(gè)開源的免費(fèi)的多協(xié)議數(shù)據(jù)傳輸開源庫(kù),該框架具備跨平臺(tái)性,開源免費(fèi),并提供了包括HTTP、FTP、SMTP、POP3等協(xié)議的功能,本文將給大家介紹C++使用LibCurl實(shí)現(xiàn)Web隱藏目錄掃描功能2023-11-11

