C++析構(gòu)函數(shù)內(nèi)部工作機制詳解
我們主要從三個方面來學(xué)習(xí)析構(gòu)函數(shù)的工作原理:
- 析構(gòu)函數(shù)的內(nèi)部工作機制
- 默認析構(gòu)函數(shù)的內(nèi)部工作機制
- 析構(gòu)函數(shù)的調(diào)用
1、析構(gòu)函數(shù)的內(nèi)部工作機制
眾所周知,在對象的生命周期結(jié)束時會自動調(diào)用析構(gòu)函數(shù)用于清理對象所申請的資源,那么它是如何清理的呢?
析構(gòu)函數(shù)會調(diào)用delete函數(shù)釋放對象中new出來的空間,即析構(gòu)函數(shù)通過delete函數(shù)來清理對象所申請的資源,當(dāng)然如果對象沒有申請資源,那么就無需調(diào)用delete函數(shù)
由于是new出來的對象是在堆上分配空間的,即使離開了作用域,其依然存在,我們必須在析構(gòu)函數(shù)中主動delete來釋放new出來的在堆上的空間,否則對象消亡后,離開了作用域后,指向該空間的數(shù)據(jù)成員(指針)就會消失,我們失去了對這片空間的控制權(quán),別人也無法使用這片空間,這就會造成內(nèi)存泄漏。
如果對象是new出來的,那么它就是一個堆對象,不會被 操作系統(tǒng)自動回收,需要我們手動調(diào)用delete函數(shù)釋放該堆對象,在delete函數(shù)中會先調(diào)用析構(gòu)函數(shù)釋放該對象所申請的資源,那么析構(gòu)函數(shù)如何釋放對象所申請的資源呢,就是前面所說的,析構(gòu)函數(shù)又會調(diào)用delete函數(shù)來釋放對象所申請的資源,當(dāng)然如果對象沒有申請資源,那么就無需調(diào)用delete函數(shù)。
#include <iostream>
using namespace std;
class Person {
public:
Person() {
cout << "調(diào)用了Person的構(gòu)造函數(shù)" << endl;
}
~Person() {
cout << "調(diào)用了Person的析構(gòu)函數(shù)" << endl;
}
private:
int name;
};
int main() {
Person* person = new Person();
delete person;
return 0;
}

2、默認析構(gòu)函數(shù)的內(nèi)部工作機制
我們清楚了析構(gòu)函數(shù)的內(nèi)部工作機制后,繼續(xù)思考一個問題,默認析構(gòu)函數(shù)它的內(nèi)部是怎么工作的呢?
我們先來看看下面這段代碼
class Time
{
public:
~Time()
{
cout << "~Time()" << endl;
}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
private:
// 基本類型(內(nèi)置類型)
int _year = 1970;
int _month = 1;
int _day = 1;
// 自定義類型
Time _t;
};
int main()
{
Date d;
return 0;
}
程序運行結(jié)束后輸出:~Time(),在main方法中根本沒有直接創(chuàng)建Time類的對象,為什么最后會調(diào)用Time類的析構(gòu)函數(shù)?
這就涉及到默認析構(gòu)函數(shù)的內(nèi)部工作機制了。
默認析構(gòu)函數(shù),對于基本類型成員不做處理,對于自定義類型成員會去調(diào)用它的析構(gòu)函數(shù)。
總結(jié): 默認構(gòu)造函數(shù)對基本類型不做處理,對自定義類型會調(diào)用它的默認構(gòu)造函數(shù),默認拷貝構(gòu)造函數(shù)對基本類型是按照字節(jié)方式直接拷貝的,對自定義類型是調(diào)用其拷貝構(gòu)造函數(shù)完成拷貝的,默認析構(gòu)函數(shù)對基本類型不做處理,對自定義類型會調(diào)用它的析構(gòu)函數(shù)。默認賦值運算符對基本類型成員變量以值的方式逐字節(jié)拷貝。而對自定義類型成員變量需要調(diào)用對應(yīng)類的賦值運算符重載完成賦值。
默認構(gòu)造函數(shù)只有一個,析構(gòu)函數(shù)只有一個,拷貝構(gòu)造函數(shù)只有一個,賦值運算符重載只有一個
如果類中沒有申請資源時,析構(gòu)函數(shù)可以不寫,直接使用編譯器生成的默認析構(gòu)函數(shù),什么事都不會干,比如Date類;有資源申請時,一定要寫,否則會造成資源泄漏
3、析構(gòu)函數(shù)的調(diào)用
析構(gòu)函數(shù)在對象消亡時被調(diào)用,以清理對象所申請的資源,那具體它在何時被調(diào)用呢?
析構(gòu)函數(shù)主要在以下4種情況下會被調(diào)用:
對象生命周期結(jié)束,此時會自動調(diào)用析構(gòu)函數(shù)。
#include<iostream>
using namespace std;
class Person {
public:
Person() {
cout << "調(diào)用了Person的構(gòu)造函數(shù)" << endl;
}
~Person() {
cout << "調(diào)用了Person的析構(gòu)函數(shù)" << endl;
}
private:
int name;
};
int main() {
Person person;
return 0;
}
運行結(jié)果如下圖所示:

該運行結(jié)果說明,在對象的生命周期結(jié)束后,會自動調(diào)用對象的析構(gòu)函數(shù)。
成員關(guān)系:對象car是對象person的成員,person的析構(gòu)函數(shù)被調(diào)用時,對象car的析構(gòu)函數(shù)也被調(diào)用。
#include <iostream>
using namespace std;
class Car {
public:
Car() {
cout << "調(diào)用了Car的構(gòu)造函數(shù)" << endl;
}
~Car() {
cout << "調(diào)用了Car的析構(gòu)函數(shù)" << endl;
}
private:
int name;
};
class Person {
public:
Person() {
cout << "調(diào)用了Person的構(gòu)造函數(shù)" << endl;
}
~Person() {
cout << "調(diào)用了Person的析構(gòu)函數(shù)" << endl;
}
private:
int name;
Car car;
};
int main() {
Person person;
return 0;
}

先調(diào)用的是包含類的析構(gòu)函數(shù),然后調(diào)用的是成員對象的析構(gòu)函數(shù)
繼承關(guān)系:當(dāng)Person是Student的父類,調(diào)用Student的析構(gòu)函數(shù),會調(diào)用Person的析構(gòu)函數(shù)。
#include <iostream>
using namespace std;
class Person {
public:
Person() {
cout << "調(diào)用了Person的構(gòu)造函數(shù)" << endl;
}
~Person() {
cout << "調(diào)用了Person的析構(gòu)函數(shù)" << endl;
}
private:
int name;
};
class Student :public Person {
public:
Student() {
cout << "調(diào)用了Student的構(gòu)造函數(shù)" << endl;
}
~Student() {
cout << "調(diào)用了Student的析構(gòu)函數(shù)" << endl;
}
private:
int name;
string no;
};
int main() {
Student student;
return 0;
}

先調(diào)用的是派生類的析構(gòu)函數(shù)釋放派生類的資源,然后調(diào)用的才是父類的析構(gòu)函數(shù)釋放父類成員所指向的資源
值得注意的是,如果派生類對象是new出來的對象,基類指針指向一個new生成的派生對象,通過delete銷毀基類指針指向的派生類對象時,有以下兩種情況:
1、 如果基類析構(gòu)函數(shù)不是虛析構(gòu)函數(shù),則只會調(diào)用基類的析構(gòu)函數(shù),派生類的析構(gòu)函數(shù)不被調(diào)用,此時派生類中申請的資源不被回收。
2、 如果基類析構(gòu)函數(shù)為虛析構(gòu)函數(shù),則釋放基類指針指向的對象時會調(diào)用基類及派生類析構(gòu)函數(shù),派生類對象中的所有資源被回收。
到此這篇關(guān)于C++析構(gòu)函數(shù)內(nèi)部工作機制詳解的文章就介紹到這了,更多相關(guān)C++析構(gòu)函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
windows 下C++生成Dump調(diào)試文件與分析
dump文件是C++程序發(fā)生異常時,保存當(dāng)時程序運行狀態(tài)的文件,是調(diào)試異常程序重要的方法,所以程序崩潰時,除了日志文件,dump文件便成了我們查找錯誤的最后一根救命的稻草,這篇文章主要介紹了windows 下C++生成Dump調(diào)試文件與分析,需要的朋友可以參考下2023-04-04
C++設(shè)置系統(tǒng)時間及系統(tǒng)時間網(wǎng)絡(luò)更新的方法
這篇文章主要介紹了C++設(shè)置系統(tǒng)時間及系統(tǒng)時間網(wǎng)絡(luò)更新的方法,涉及網(wǎng)絡(luò)程序設(shè)計與系統(tǒng)函數(shù)的使用,需要的朋友可以參考下2014-10-10

