C++淺析析構(gòu)函數(shù)的特征
定義
析構(gòu)函數(shù):與構(gòu)造函數(shù)功能相反,析構(gòu)函數(shù)不是完成對象的銷毀,局部對象銷毀工作是由編譯器完成的。而對象在銷毀時會自動調(diào)用析構(gòu)函數(shù),完成類的一些資源清理工作
特征
1. 析構(gòu)函數(shù)名是在類名前加上字符 ~。
2. 無參數(shù)無返回值。
3. 一個類有且只有一個析構(gòu)函數(shù)。若未顯式定義,系統(tǒng)會自動生成默認(rèn)的析構(gòu)函數(shù)。
4. 對象生命周期結(jié)束時,C++編譯系統(tǒng)系統(tǒng)自動調(diào)用析構(gòu)函數(shù)
舉一個例子,大家來看下面的代碼
typedef int DataType;
class SeqList
{
public:
SeqList(int capacity = 10)
{
_pData = (DataType*)malloc(capacity * sizeof(DataType));
assert(_pData);
_size = 0;
_capacity = capacity;
}
private:
int* _pData;
size_t _size;
size_t _capacity;
};我們都知道一般malloc了空間之后,我們都需要用free來釋放空間。
而在實際操作當(dāng)中,我們有時候會忽略free,而直接運行代碼。
所以為了方便我們使用,這里的析構(gòu)函數(shù),相當(dāng)于程序自動幫你補了一個free出來。
具體代碼:
typedef int DataType;
class SeqList
{
public:
SeqList(int capacity = 10)
{
_pData = (DataType*)malloc(capacity * sizeof(DataType));
assert(_pData);
_size = 0;
_capacity = capacity;
}
~SeqList()
{
if (_pData)
{
free(_pData); // 釋放堆上的空間
_pData = NULL; // 將指針置為空
_capacity = 0;
_size = 0;
}
}
private:
int* _pData;
size_t _size;
size_t _capacity;
};
編譯器生成的默認(rèn)析構(gòu)函數(shù)
編譯器默認(rèn)生成的析構(gòu)函數(shù)能做些什么工作呢?我們前面已經(jīng)介紹了編譯器生成的構(gòu)造函數(shù)會去只會處理自定義類型的成員變量,那么析構(gòu)既然和構(gòu)造相對應(yīng),析構(gòu)也應(yīng)該是只去處理自定義類型的成員變量吧,確實如此,析構(gòu)函數(shù)不會對內(nèi)置類型有任何處理,只會在調(diào)用自身的析構(gòu)后再去調(diào)用自定義類型成員的析構(gòu)。
關(guān)于編譯器自動生成的析構(gòu)函數(shù),下面的程序我們會看到,編譯器生成的析構(gòu)函數(shù),會對自定類型成員調(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ù)對成員變量的處理
- 內(nèi)置類型不處理;
- 自定義類型成員調(diào)用相應(yīng)的析構(gòu)函數(shù);
那成員變量中的內(nèi)置類型處不處理其實都無所謂嘛,反正都要歸還給操作系統(tǒng),但是有例外:

如果成員變量含有指針,并且指針指向一塊我們正使用的空間,指針也是內(nèi)置類型,那如果不釋放指針指向的那塊空間就會造成內(nèi)存泄漏,而編譯器生成的析構(gòu)函數(shù)是不會處理此情況的,因為需要我們在析構(gòu)函數(shù)中主動釋放內(nèi)存,也就是說需要我們顯式的去定義析構(gòu)函數(shù)。
class Stack
{
public:
Stack(int capacity = 4)
:
_size(0),
_capacity(capacity),
_p(new int[_capacity])//使用new去申請內(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ù)無論是我們顯式定義的還是編譯器生成的,都會在對象的聲明周期結(jié)束時自動調(diào)用,并且會調(diào)用自定義類型成員變量的析構(gòu)函數(shù)來釋放資源,而對內(nèi)置類型不做處理。
可以不顯式定義析構(gòu)函數(shù)的情況
- 類的成員都是自定義類型的;
- 類的成員都是非指針的內(nèi)置類型;
- 成員有指針,但并沒有管理內(nèi)存資源;
如果類的成員變量有指針類型,并且我們讓指針指向了一塊動態(tài)分配的空間,那么就需要我們自己寫析構(gòu)函數(shù)了。
到此這篇關(guān)于C++淺析析構(gòu)函數(shù)的特征的文章就介紹到這了,更多相關(guān)C++析構(gòu)函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
openCV中meanshift算法查找目標(biāo)的實現(xiàn)
本文主要介紹了openCV中meanshift算法查找目標(biāo)的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11
C++瓦片地圖坐標(biāo)轉(zhuǎn)換的實現(xiàn)詳解
常見的瓦片地圖有矩形、菱形、正六邊形幾種。此文章主要討論菱形瓦片,也就是大家常說的2.5D,斜45度瓦片地圖。比如《紅警2》、《帝國時代2》都是采用這種技術(shù)2022-09-09
一文詳解C語言中的switch語句和while循環(huán)
這篇文章主要給大家詳細(xì)介紹了C語言中的switch語句和while循環(huán),文中通過代碼示例給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2023-12-12
C++ opencv ffmpeg圖片序列化實現(xiàn)代碼解析
這篇文章主要介紹了C++ opencv ffmpeg圖片序列化實現(xiàn)代碼解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-08-08
C++設(shè)計模式編程中的迭代器模式應(yīng)用解析
這篇文章主要介紹了C++設(shè)計模式編程中的迭代器模式應(yīng)用解析,迭代器模式注重對集合中元素的遍歷而不使其暴露,需要的朋友可以參考下2016-03-03
C++基礎(chǔ)學(xué)習(xí)之函數(shù)重載的簡單介紹
函數(shù)重載是一種特殊情況,C++允許在同一作用域中聲明幾個類似的同名函數(shù),這些同名函數(shù)的形參列表(參數(shù)個數(shù),類型,順序)必須不同,常用來處理實現(xiàn)功能類似數(shù)據(jù)類型不同的問題。這篇文章主要給大家介紹了關(guān)于C++基礎(chǔ)學(xué)習(xí)之函數(shù)重載的相關(guān)資料,需要的朋友可以參考下2019-01-01

