預設建構函式 建構函式 複製建構函式和賦值操作符

2021-07-26 14:06:57 字數 2400 閱讀 8810

這幾個概念比較容易混淆,總結一下。

預設建構函式是沒有引數、和類同名的建構函式。

當乙個類沒有任何建構函式時,編譯器將會合成乙個預設建構函式。

那麼編譯器合成的預設建構函式是做什麼用的呢?是初始化類的成員變數嗎?

事實上不是。編譯器合成的預設建構函式只是滿足編譯器的需要,而不是按照程式設計師想的去做。

更詳細的內容可參考:

談一談預設建構函式

編譯器合成的預設建構函式初始化的成員變數包括兩類。

1、內建型別。如果內建型別變數作用域為全域性作用域或者為靜態區域性變數,那麼將初始化為0。為區域性作用域的內建變數不做初始化。

2、類型別。如果類的成員變數包括類型別,那麼合成的成員變數將呼叫這個類的預設建構函式來初始化類型別成員變數。

舉個例子。

[cpp]view plain

copy

class

a    

intnum;  

};  

class

b  ;  

intb::k;  

intmain()    

看到的輸出結果是:

-842150451 0

100

非預設建構函式是我們自己設計的,通常含有引數。目的同樣是初始化類成員變數。

當我們設計了類的非預設建構函式,而沒有設計預設建構函式,這時候編譯器就不會合成預設建構函式了。乙個類,如果沒有預設建構函式,那麼將會有以下限制

1、在建立類成員時,必須顯示呼叫非預設建構函式,傳入引數初始化類成員變數。

2、這個類將不能用作動態分配陣列的元素型別。這是因為動態陣列元素初始化會呼叫預設建構函式。

3、這個類如果作為靜態陣列型別,必須提供顯示呼叫建構函式。

4、這個類的物件如果儲存到容器中。那麼就不允許使用接受容器大小而沒有提供乙個顯示初始化式的建構函式。

在實際應用中,當我們設計了乙個非預設建構函式,那麼再設計乙個預設建構函式總是「有益無害」的。

通常在非預設建構函式初始化類的成員變數時有兩種方法,一是初始化列表中初始化,二是在建構函式體內初始化。這是有區別的,可以認為建構函式分兩階段執行。1初始化階段,2普通計算階段,這個是值建構函式體內執行的語句。

可以這樣理解,在初始化列表中初始化成員變數,是在變數定義的同時初始化;而在函式體內初始化就是先定義後初始化了。對於引用和const變數,只能在初始化列表中初始化。

還有乙個就是變數的初始化順序。在初始化列表中初始化的變數並不是按照指定的次序來初始化的,而是按照變數的定義順序類初始化的。乙個好的習慣就是不用乙個成員變數來初始化另外乙個成員變數。

非預設建構函式可以用來到類型別的轉換。可以用單個實參的建構函式到類型別的轉換。乙個例子:

[cpp]view plain

copy

class

a  a(int

k)  

intnum;  

};  

intmain()  

cout

0;  

}  

輸出:0

10 如果我們不想這樣的轉換,即禁止隱式呼叫,宣告函式為explicit即可。

複製建構函式是只有單個形參,且形參是本型別的引用(常用const修飾)。

複製建構函式在以下情況下呼叫

1、用乙個同型別的物件初始化另乙個物件。

2、複製乙個物件,將它作為實參船體給乙個函式。

3、函式返回值為這個類型別(非引用),返回時複製這個物件。

4、初始化順序容器的元素。

同預設建構函式一樣,當我們沒有定義複製建構函式時,編譯器會合成乙個預設的複製建構函式。合成的複製建構函式只是滿足編譯器的需求,把新物件的每個成員變數初始化為原物件的副本,通常是大家所說的淺拷貝。一般來說合成的複製建構函式能滿足我們的需求,但是包含有指標的類一般情況下需要定義自己的複製建構函式。

關於深拷貝淺拷貝可參考:memberwise copy(深拷貝)與bitwise copy(淺拷貝)的區別

至於有指標的類為什麼需要複製建構函式可參考:c++中的智慧型指標

有時候我們禁止物件的複製,這時只需要把複製建構函式宣告為private。

複製操作符是指等號「=」。對於類,是指過載賦值操作符。

像複製建構函式一樣,如果我們沒有定義複製操作符,編譯器會合成複製操作符,功能像複製建構函式一樣,逐個初始化類成員。

什麼情況下呼叫的複製建構函式?什麼情況下用賦值操作符?

賦值操作符是雙目運算子,在兩個物件都存在情況下,乙個物件給另乙個物件複製用賦值操作符。

而複製建構函式是只有乙個引數。

例如a乙個類,a是類a的乙個物件

a a2(a);呼叫複製建構函式。

a a2=a;同樣呼叫複製建構函式

下面例子呼叫賦值操作符

a a3;

a3=a;這時候a3已經存在了。 

拷貝建構函式(複製建構函式)

執行 物件a 物件b時,系統需要呼叫拷貝建構函式,如果程式設計師沒寫,則呼叫預設的拷貝建構函式。預設的拷貝建構函式利用淺拷貝方式,它的樣子是 a const a a 淺拷貝 拷貝的時候,兩個指標指向同乙個區域 char str1 helloworld char str2 str1 深拷貝 拷貝的時候...

預設建構函式和合成預設建構函式

當我們沒有為類中的物件提供初始值,此時就會執行預設初始化,類會通過乙個特殊的建構函式來控制預設初始化過程,這個函式叫做預設建構函式,這個函式並不需要任何的實參,但是如果我們的類沒有顯式地定義建構函式,那麼編譯器就會為我們隱式地定義乙個預設建構函式 只要沒有顯式定義建構函式,編譯器就會提供預設建構函式...

預設建構函式

只要定義乙個物件時沒有提供初始化式,就使用預設建構函式。為所有形參提供預設實參的建構函式也定義了預設建構函式。乙個類哪怕只定義了乙個建構函式,編譯器也不會再生成預設建構函式。這條規則的根據是,如果乙個類在某種情況下需要控制物件初始化,則該類很可能在所有情況下都需要控制。合成的預設建構函式 synth...