C++超詳細(xì)講解析構(gòu)函數(shù)
特性
析構(gòu)函數(shù)是特殊的成員函數(shù)
特征如下:
- 析構(gòu)函數(shù)名是~類名;
- 無(wú)參數(shù)無(wú)返回值;
- 一個(gè)類有且只有一個(gè)析構(gòu)函數(shù);
- 對(duì)象聲明周期結(jié)束,編譯器自動(dòng)調(diào)用析構(gòu)函數(shù);
class Stack
{
public:
Stack(int capacity = 4)
:
_size(0),
_capacity(capacity),
_p(new int[_capacity])
{
cout << "Stack(int capacity = 4)" << endl;
}
~Stack()
{
cout << "~Stack()" << endl;
if (_p)
{
delete[](_p);
_p = nullptr;
}
_size = _capacity = 0;
}
private:
int _capacity;
int _size;
int* _p;
};
int main()
{
Stack s;
return 0;//程序結(jié)束,調(diào)用s的析構(gòu)函數(shù)
}
輸出:

析構(gòu)函數(shù)處理自定義類型
class String
{
public:
String(const char* str = "songxin")
{
cout << "String(const char* str = \"songxin\")" << endl;
_str = (char*)malloc(strlen(str) + 1);
strcpy(_str, str);
}
~String()
{
cout << "~String()" << endl;
free(_str);
_str = nullptr;
}
private:
char* _str;
};
class Person
{
public:
Person()
:
_age(20),
_name()
{
cout << "Person()" << endl;
}
~Person()
{
cout << "~Person()" << endl;
}
private:
String _name;
int _age;
};
int main()
{
Person p;
return 0;
}
輸出:

析構(gòu)函數(shù)在程序即將結(jié)束時(shí),調(diào)用了Person的析構(gòu)函數(shù),在Person類的析構(gòu)函數(shù)即將結(jié)束接著調(diào)用String類的析構(gòu)函數(shù)。
歸納一下:
析構(gòu)函數(shù)是與構(gòu)造函數(shù)執(zhí)行相反的操作的,構(gòu)造函數(shù)負(fù)責(zé)給對(duì)象成員變量初始化并加載資源,而析構(gòu)函數(shù)則是給對(duì)象的成員變量清理資源,而不是清理對(duì)象本身。
編譯器生成的默認(rèn)析構(gòu)函數(shù)
編譯器默認(rèn)生成的析構(gòu)函數(shù)能做些什么工作呢?我們前面已經(jīng)介紹了編譯器生成的構(gòu)造函數(shù)會(huì)去只會(huì)處理自定義類型的成員變量,那么析構(gòu)既然和構(gòu)造相對(duì)應(yīng),析構(gòu)也應(yīng)該是只去處理自定義類型的成員變量吧,確實(shí)如此,析構(gòu)函數(shù)不會(huì)對(duì)內(nèi)置類型有任何處理,只會(huì)在調(diào)用自身的析構(gòu)后再去調(diào)用自定義類型成員的析構(gòu)。
關(guān)于編譯器自動(dòng)生成的析構(gòu)函數(shù),下面的程序我們會(huì)看到,編譯器生成的析構(gòu)函數(shù),會(huì)對(duì)自定類型成員調(diào)用它的析構(gòu)函數(shù)。
class String
{
public:
String(const char* str = "songxin")
{
cout << "String(const char* str = \"songxin\")" << endl;
_str = (char*)malloc(strlen(str) + 1);
strcpy(_str, str);
}
~String()
{
cout << "~String()" << endl;
free(_str);
_str = nullptr;
}
private:
char* _str;
};
class Person
{
public:
Person()
:
_age(20),
_name()
{
cout << "Person()" << endl;
}
private:
String _name;
int _age;
};
int main()
{
Person p;
return 0;
}
輸出:

默認(rèn)生成的析構(gòu)函數(shù)對(duì)成員變量的處理
- 內(nèi)置類型不處理;
- 自定義類型成員調(diào)用相應(yīng)的析構(gòu)函數(shù);
那成員變量中的內(nèi)置類型處不處理其實(shí)都無(wú)所謂嘛,反正都要?dú)w還給操作系統(tǒng),但是有例外:

如果成員變量含有指針,并且指針指向一塊我們正使用的空間,指針也是內(nèi)置類型,那如果不釋放指針指向的那塊空間就會(huì)造成內(nèi)存泄漏,而編譯器生成的析構(gòu)函數(shù)是不會(huì)處理此情況的,因?yàn)樾枰覀冊(cè)谖鰳?gòu)函數(shù)中主動(dòng)釋放內(nèi)存,也就是說(shuō)需要我們顯式的去定義析構(gòu)函數(shù)。
class Stack
{
public:
Stack(int capacity = 4)
:
_size(0),
_capacity(capacity),
_p(new int[_capacity])//使用new去申請(qǐng)內(nèi)存
{
cout << "Stack(int capacity = 4)" << endl;
}
~Stack()
{
cout << "~Stack()" << endl;
if (_p)
{
delete[](_p);//釋放內(nèi)存
_p = nullptr;
}
_size = _capacity = 0;
}
private:
int _capacity;
int _size;
int* _p;
};
int main()
{
Stack s;
return 0;//程序結(jié)束,調(diào)用s的析構(gòu)函數(shù)
}
析構(gòu)函數(shù)無(wú)論是我們顯式定義的還是編譯器生成的,都會(huì)在對(duì)象的聲明周期結(jié)束時(shí)自動(dòng)調(diào)用,并且會(huì)調(diào)用自定義類型成員變量的析構(gòu)函數(shù)來(lái)釋放資源,而對(duì)內(nèi)置類型不做處理。
可以不顯式定義析構(gòu)函數(shù)的情況
- 類的成員都是自定義類型的;
- 類的成員都是非指針的內(nèi)置類型;
- 成員有指針,但并沒(méi)有管理內(nèi)存資源;
如果類的成員變量有指針類型,并且我們讓指針指向了一塊動(dòng)態(tài)分配的空間,那么就需要我們自己寫析構(gòu)函數(shù)了。
總結(jié):不是類直接管理另一塊內(nèi)存資源的,就不需要寫析構(gòu)函數(shù),編譯器自己生成的就能處理。
到此這篇關(guān)于C++超詳細(xì)講解析構(gòu)函數(shù)的文章就介紹到這了,更多相關(guān)C++析構(gòu)函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言 makefile學(xué)習(xí)及實(shí)現(xiàn)實(shí)例
這篇文章主要介紹了C語(yǔ)言 makefile學(xué)習(xí)及實(shí)現(xiàn)實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-03-03
基于Qt制作一個(gè)定時(shí)關(guān)機(jī)的小程序
這篇文章主要為大家詳細(xì)介紹了如何基于Qt制作一個(gè)有趣的定時(shí)關(guān)機(jī)的小程序,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12
C++基于EasyX圖形庫(kù)實(shí)現(xiàn)2048小游戲
這篇文章主要為大家詳細(xì)介紹了C++基于EasyX圖形庫(kù)實(shí)現(xiàn)2048小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02
VC6.0打開(kāi)文件以及向工程中添加文件時(shí)程序崩潰自動(dòng)退出解決方法
vc6.0程序中,點(diǎn)擊打開(kāi)文件以及向工程中添加文件時(shí),程序竟然崩潰自動(dòng)退出了,不知什么原因,安裝相同的vc程序,本本竟然出現(xiàn)此緣故2013-01-01

