1. 程式人生 > 其它 >C++類四大隱藏函式詳解(建構函式、解構函式、拷貝構造、賦值函式)

C++類四大隱藏函式詳解(建構函式、解構函式、拷貝構造、賦值函式)

技術標籤:C++程式語言記憶體管理c++解構函式

建構函式傳送門

一、解構函式

1、什麼是解構函式

​ 與建構函式一樣也是一種特殊的成員函式,它會在物件釋放的時候自動呼叫,負責一些收尾工作,如:儲存資料、釋放資源等。

2、函式格式

~類名(void)
{
    
}

3、解構函式的任務

​ 負責釋放在建構函式中獲取到的所有資源。

​ 執行過程:

​ 1、先執行解構函式本身程式碼

​ 2、呼叫成員變數的解構函式

​ 3、呼叫父類的解構函式

  • 注意:解構函式與建構函式的執行順序剛好相反
#include <iostream>
using namespace std;

class Test
{
public: Test(void) { cout<<"我是建構函式"<<endl; } ~Test(void) { cout<<"我是解構函式"<<endl; } }; void func(void) { Test* t = new Test; cout<<"-------"<<endl; delete t; } int main(int argc,const char* argv[]) { int n=3; while(n--
) func(); }

二、預設的解構函式,建構函式

1、 定義

在設計一個類時,如果沒有顯示實現建構函式與解構函式,編譯器 會自動生成它們,也叫預設的構造和解構函式。

但生成的並不是真正語法意義上的函式,而是功能意義上的函式。

編譯器做為可執行指令的生成著,它有能力直接生成某些功能的二進位制指令,不需要藉助語言上的函式完成某些任務。

2、 什麼時候需要顯示實現建構函式

  1. 有成員需要初始化
  2. 需要一些引數做一些準備工作
  3. 需要在物件使用之前準備一些資源.如:申請一些堆記憶體

3.、什麼時候需要顯示實現解構函式

預設的解構函式會自動釋放編譯器能看得到的所有資源。如:成員變數,類成員,父類

  1. 儲存一些資料
  2. 成員變數中有指標,且指向堆記憶體。

三、類物件 建立過程與釋放記憶體總結

建立:

分配記憶體 -> 父類構造 -> 成員構造 -> 自己的構造(初始化成員,申請準備記憶體等)

​ 父類構造:按照繼承表的順序從左到右依次執行父類建構函式

​ 成員構造:按照成員的宣告順序,從上到下依次執行成員變數的建構函式

釋放:

自己的解構函式(儲存資料,釋放堆記憶體等) -> 成員析構 -> 父類的析構 -> 釋放記憶體(物件)

​ 成員析構:按照宣告的順序,從下到上依次執行成員變數的解構函式

​ 父類析構:按照繼承表從右到左依次執行父類的解構函式。

四、拷貝建構函式(賦值構造)

什麼是拷貝建構函式

​ 是一種特殊的建構函式,當使用一個物件初始化另一個新的物件時,就會呼叫隱藏的拷貝建構函式,它也是類自帶建構函式之一,由編譯器自動生成。

拷貝構造格式

類名(const 類名& 變數名)
{
    
}

呼叫拷貝構造

  1. 類名 物件 = 物件
  2. 使用物件作為函式的引數時(不使用引用)

拷貝構造的任務

​ 負責把舊的類物件中的成員拷貝給新的物件(預設,淺拷貝)。

什麼時候顯式使用拷貝構造?

​ 當類中有成員是指標,且該指標指向了一塊堆記憶體,此時拷貝構造應該拷貝指標所指向的記憶體(深拷貝),而預設的淺拷貝只拷貝指標變數的值,這時候會導致指標指向的記憶體被delete從而記憶體崩潰,因此應該顯示地拷貝構造。

#include <iostream>
using namespace std;

class Test
{
	int num;
public:
	Test(int num)
	{
		this->num = num;
	}

	Test(Test& t)
	{
		num = t.num;
		cout << "我是拷貝構造" << endl;
	}

	void show(void)
	{
		cout << num << endl;
	}
};

void func(Test t)
{
	cout << __func__ << endl;
}

int main(int argc,const char* argv[])
{
	Test t(100);

	Test t1 = t;	// 呼叫拷貝構造
	t.show();
	t1.show();

	func(t);
}

七、賦值函式(賦值運算子)

什麼是賦值函式

​ 在C++中是把運算子當做函式處理的,當一個物件給另一個物件賦值時就會自動呼叫該函式

賦值函式格式

& operator=(const& that)
{
    
}
#include <iostream>
using namespace std;

class Test
{
	int num;
public:
	Test(int num)
	{
		this->num = num;
	}

	void show(void)
	{
		cout << num << endl;
	}

	Test& operator=(const Test& that)
	{
		num = that.num;
		cout << "我是賦值函式" << endl;
		return *this;
	}
};

int main(int argc,const char* argv[])
{
	Test t(100);
	Test t1(0);
	(t1 = t).show(); 		//呼叫賦值函式
}

什麼時候呼叫

​ 物件 = 物件;

賦值函式的任務

​ 與拷貝建構函式一樣,負責把一個物件的記憶體拷貝給另一個物件(淺拷貝)。

什麼時候顯式實現賦值函式:

​ 當需要顯式實現拷貝構造時,就應該顯示實現賦值函式。