溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C++析構(gòu)函數(shù)內(nèi)部工作機(jī)制是什么

發(fā)布時(shí)間:2023-02-27 14:08:04 來源:億速云 閱讀:184 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容主要講解“C++析構(gòu)函數(shù)內(nèi)部工作機(jī)制是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“C++析構(gòu)函數(shù)內(nèi)部工作機(jī)制是什么”吧!

1、析構(gòu)函數(shù)的內(nèi)部工作機(jī)制

眾所周知,在對(duì)象的生命周期結(jié)束時(shí)會(huì)自動(dòng)調(diào)用析構(gòu)函數(shù)用于清理對(duì)象所申請(qǐng)的資源,那么它是如何清理的呢?

析構(gòu)函數(shù)會(huì)調(diào)用delete函數(shù)釋放對(duì)象中new出來的空間,即析構(gòu)函數(shù)通過delete函數(shù)來清理對(duì)象所申請(qǐng)的資源,當(dāng)然如果對(duì)象沒有申請(qǐng)資源,那么就無需調(diào)用delete函數(shù)

由于是new出來的對(duì)象是在堆上分配空間的,即使離開了作用域,其依然存在,我們必須在析構(gòu)函數(shù)中主動(dòng)delete來釋放new出來的在堆上的空間,否則對(duì)象消亡后,離開了作用域后,指向該空間的數(shù)據(jù)成員(指針)就會(huì)消失,我們失去了對(duì)這片空間的控制權(quán),別人也無法使用這片空間,這就會(huì)造成內(nèi)存泄漏。

如果對(duì)象是new出來的,那么它就是一個(gè)堆對(duì)象,不會(huì)被 操作系統(tǒng)自動(dòng)回收,需要我們手動(dòng)調(diào)用delete函數(shù)釋放該堆對(duì)象,在delete函數(shù)中會(huì)先調(diào)用析構(gòu)函數(shù)釋放該對(duì)象所申請(qǐng)的資源,那么析構(gòu)函數(shù)如何釋放對(duì)象所申請(qǐng)的資源呢,就是前面所說的,析構(gòu)函數(shù)又會(huì)調(diào)用delete函數(shù)來釋放對(duì)象所申請(qǐng)的資源,當(dāng)然如果對(duì)象沒有申請(qǐ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;
}

C++析構(gòu)函數(shù)內(nèi)部工作機(jī)制是什么

2、默認(rèn)析構(gòu)函數(shù)的內(nèi)部工作機(jī)制

我們清楚了析構(gòu)函數(shù)的內(nèi)部工作機(jī)制后,繼續(xù)思考一個(gè)問題,默認(rèn)析構(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;
}

程序運(yùn)行結(jié)束后輸出:~Time(),在main方法中根本沒有直接創(chuàng)建Time類的對(duì)象,為什么最后會(huì)調(diào)用Time類的析構(gòu)函數(shù)?

這就涉及到默認(rèn)析構(gòu)函數(shù)的內(nèi)部工作機(jī)制了。

默認(rèn)析構(gòu)函數(shù),對(duì)于基本類型成員不做處理,對(duì)于自定義類型成員會(huì)去調(diào)用它的析構(gòu)函數(shù)。

總結(jié): 默認(rèn)構(gòu)造函數(shù)對(duì)基本類型不做處理,對(duì)自定義類型會(huì)調(diào)用它的默認(rèn)構(gòu)造函數(shù),默認(rèn)拷貝構(gòu)造函數(shù)對(duì)基本類型是按照字節(jié)方式直接拷貝的,對(duì)自定義類型是調(diào)用其拷貝構(gòu)造函數(shù)完成拷貝的,默認(rèn)析構(gòu)函數(shù)對(duì)基本類型不做處理,對(duì)自定義類型會(huì)調(diào)用它的析構(gòu)函數(shù)。默認(rèn)賦值運(yùn)算符對(duì)基本類型成員變量以值的方式逐字節(jié)拷貝。而對(duì)自定義類型成員變量需要調(diào)用對(duì)應(yīng)類的賦值運(yùn)算符重載完成賦值。

默認(rèn)構(gòu)造函數(shù)只有一個(gè),析構(gòu)函數(shù)只有一個(gè),拷貝構(gòu)造函數(shù)只有一個(gè),賦值運(yùn)算符重載只有一個(gè)

如果類中沒有申請(qǐng)資源時(shí),析構(gòu)函數(shù)可以不寫,直接使用編譯器生成的默認(rèn)析構(gòu)函數(shù),什么事都不會(huì)干,比如Date類;有資源申請(qǐng)時(shí),一定要寫,否則會(huì)造成資源泄漏

3、析構(gòu)函數(shù)的調(diào)用

析構(gòu)函數(shù)在對(duì)象消亡時(shí)被調(diào)用,以清理對(duì)象所申請(qǐng)的資源,那具體它在何時(shí)被調(diào)用呢?

析構(gòu)函數(shù)主要在以下4種情況下會(huì)被調(diào)用:

對(duì)象生命周期結(jié)束,此時(shí)會(huì)自動(dòng)調(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;
}

運(yùn)行結(jié)果如下圖所示:

C++析構(gòu)函數(shù)內(nèi)部工作機(jī)制是什么

該運(yùn)行結(jié)果說明,在對(duì)象的生命周期結(jié)束后,會(huì)自動(dòng)調(diào)用對(duì)象的析構(gòu)函數(shù)。

成員關(guān)系:對(duì)象car是對(duì)象person的成員,person的析構(gòu)函數(shù)被調(diào)用時(shí),對(duì)象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;
}

C++析構(gòu)函數(shù)內(nèi)部工作機(jī)制是什么

先調(diào)用的是包含類的析構(gòu)函數(shù),然后調(diào)用的是成員對(duì)象的析構(gòu)函數(shù)

繼承關(guān)系:當(dāng)Person是Student的父類,調(diào)用Student的析構(gòu)函數(shù),會(huì)調(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;
}

C++析構(gòu)函數(shù)內(nèi)部工作機(jī)制是什么

先調(diào)用的是派生類的析構(gòu)函數(shù)釋放派生類的資源,然后調(diào)用的才是父類的析構(gòu)函數(shù)釋放父類成員所指向的資源

值得注意的是,如果派生類對(duì)象是new出來的對(duì)象,基類指針指向一個(gè)new生成的派生對(duì)象,通過delete銷毀基類指針指向的派生類對(duì)象時(shí),有以下兩種情況:

1、 如果基類析構(gòu)函數(shù)不是虛析構(gòu)函數(shù),則只會(huì)調(diào)用基類的析構(gòu)函數(shù),派生類的析構(gòu)函數(shù)不被調(diào)用,此時(shí)派生類中申請(qǐng)的資源不被回收。

2、 如果基類析構(gòu)函數(shù)為虛析構(gòu)函數(shù),則釋放基類指針指向的對(duì)象時(shí)會(huì)調(diào)用基類及派生類析構(gòu)函數(shù),派生類對(duì)象中的所有資源被回收。

到此,相信大家對(duì)“C++析構(gòu)函數(shù)內(nèi)部工作機(jī)制是什么”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

c++
AI