C++中建構函式,拷貝建構函式和賦值函式的詳解

nihao_2016發表於2020-12-12

C++中一般建立物件,拷貝或賦值的方式有建構函式,拷貝建構函式,賦值函式這三種方法。下面就詳細比較下三者之間的區別以及它們的具體實現。

 

1. 建構函式

建構函式有哪些特點:

a.建構函式的命名必須和類的命名相同。

b.如果一個類中沒有定義建構函式的話,編譯器會預設新增建構函式,該建構函式為無參構造。

c.建構函式完成類的成員變數的初始化和物件的記憶體的申請。類成員變數初始化有兩種方式:1、可以在類內定義的時候通過初始化列表的情況下進行初始化。2、可以通過在類外定義建構函式內完成初始化。

d. 建構函式可以實現過載,可以帶一個或多個引數,解構函式則不能被過載,只能定義一個。

class Animal
{
public:
	int m_color; //顏色
	Animal();            //無參建構函式
	Animal(int type);    //帶參建構函式
	virtual ~Animal();  //解構函式,未定義的情況下編譯器會新增預設解構函式

	void Eat(void)
	{
		cout << "Aninal Eat" << endl;
	}
};

 另外說明一下:

一個C++的空類,編譯器會加入哪些預設的成員函式:

預設建構函式和拷貝建構函式

解構函式

賦值函式(賦值運算子)

取值函式

**即使程式沒定義任何成員,編譯器也會插入以上的函式!

 

2. 拷貝建構函式

建構函式的特點:

a.拷貝建構函式可以理解為一種特殊的建構函式,函式名和類名相同,引數為為類的引用。

b.拷貝構造應用在對沒有初始化的物件用已經存在的物件進行初始化操作。

c.在類內未定義的情況下,編譯器也會新增預設拷貝建構函式。

在C++中,3種物件需要複製,此時拷貝建構函式會被呼叫

  1. 一個物件以值傳遞的方式傳入函式體
  2. 一個物件以值傳遞的方式從函式返回
  3. 一個物件需要通過另一個物件進行初始化

例如:

Animal dog1;  //呼叫建構函式

Animal dog2(dog1);//呼叫拷貝建構函式

Animal dog2=dog1; //呼叫拷貝建構函式

因為系統提供的預設拷貝建構函式工作方式是淺拷貝。如果物件中用到了需要手動釋放的物件,則會出現問題,這時就要手動過載拷貝建構函式,實現深拷貝。

下面說說深拷貝與淺拷貝:

  1. 淺拷貝:如果複製的物件中引用了一個外部內容(例如分配在堆上的資料),那麼在複製這個物件的時候,讓新舊兩個物件指向同一個外部內容,就是淺拷貝。(指標雖然複製了,但所指向的空間內容並沒有複製,而是由兩個物件共用,兩個物件不獨立,刪除空間存在)
  2. 深拷貝:如果在複製這個物件的時候為新物件製作了外部物件的獨立複製,就是深拷貝。

拷貝建構函式的定義:

class Animal
{
public:
	int m_color; //顏色
	Animal();
	Animal(int type);
	Animal(const Animal& Ani) //拷貝建構函式
	{
		cout << "拷貝構造" << endl;
	}
}

3. 賦值函式

賦值函式的特點:

a.賦值函式是對“=”賦值操作符的過載,可以通過賦值的形式對兩外一個物件的成員進行者賦值。

b.一個物件對另一個物件賦值時,兩個物件都是已經初始化過的。

拷貝構造和賦值函式的區別:

1)拷貝建構函式是一個物件初始化一塊記憶體區域,這塊記憶體就是新物件的記憶體區,而賦值函式是對於一個已經被初始化的物件來進行賦值操作。

2)一般來說在資料成員包含指標物件的時候,需要考慮兩種不同的處理需求:一種是複製指標物件,另一種是引用指標物件。拷貝建構函式大多數情況下是複製,而賦值函式是引用物件

3)實現不一樣。拷貝建構函式首先是一個建構函式,它呼叫時候是通過引數的物件初始化產生一個物件。賦值函式則是把一個新的物件賦值給一個原有的物件,所以如果原來的物件中有記憶體分配要先把記憶體釋放掉,而且還要檢察一下兩個物件是不是同一個物件,如果是,不做任何操作,直接返回。

 

拷貝構造和賦值函式的應用:

Animal dog1; //呼叫建構函式
Animal dog2=dog1; //呼叫拷貝建構函式,此處dog2物件不存在
Animal dog3; 
dog3 = dog2; //呼叫賦值過載函式

 

注:本部落格參考了:https://www.jb51.net/article/158473.htm

 

相關文章