《深度探索C 物件模型》第二章 建構函式語意學

2021-07-28 06:42:05 字數 3096 閱讀 2419

default constructor的構建操作

default constructors在需要的時候被編譯器產生。

例:

clas foo

void foo_bar()

}

上述的**情況中,並不會生成乙個deafult constructor。

需要注意的地方是:

全域性的object內存在被啟用時會清0,而區域性物件配置於堆疊中,不一定會清0,它們的內容是記憶體上次被使用的遺留值。

接下來分4種情況討論編譯器會產生default constructor的情況:

①帶有預設構造器的member class object

如果乙個類中包含乙個成員物件,這個物件含有default constructor,那麼這個類隱含生成的預設構造器就是有用的(nontrivial),這個合成造作只有真正需要被呼叫的時候才會產生。

那麼乙個問題產生了,在c++不同的編譯模組中,怎麼避免合成出多個default constructor呢?解決辦法就是把合成的預設構造器,拷貝構造器,喜購氣,拷貝構造操作符都以inline的方式完成,具有靜態鏈結,不會被檔案外的人看到,如果函式太複雜,會合成乙個顯式的非內聯靜態實體。被合成的default constructor是滿足編譯器的需要而不是程式設計師的需要!!

如果乙個類a內涵乙個或乙個以上的member class object,那麼a的每乙個構造器都會呼叫子類的預設構造器,編譯器會擴充套件已經存在的構造器,在其中安插一些**,使得使用者**在被執行前,先呼叫必要的預設構造器。

②帶有default constructor的base class

如果子類的父類有預設構造器,那麼子類生成的預設構造器會自動呼叫父類的預設構造器,對於後繼承的類而言,這個合成的構造器和預設構造器沒什麼區別。

乙個帶有virtual function的class

1.乙個class宣告了或者繼承了乙個虛函式。

2.class派生自乙個繼承串鏈中,其中有虛基類,會發生擴張操作:

①乙個虛函式表會被編譯器產生出來,內放有類的虛函式位址。

②每乙個類物件中,乙個額外的指標成員會被編譯器合成出來,內含相關的虛表位址。

帶有乙個virtual base class的class

總結:一共有4中情況會導致」編譯器必須為未宣告constructor的類合成乙個預設的構造器「,被合成出來的構造器只能滿足編譯器的需要,而其它情況並不會被合成出來。

而在合成出來的預設構造器中,只有基類子物件(base class subobject)和成員類物件會被初始化,其它的nonstatic data members比如int,float都不會被初始化。

c++新手的兩個誤解

1.任何類如果沒有定義預設構造器,就會被合成出乙個來。

2.合成出來的預設構造器會被明確設定」class內每乙個資料成員的預設值「。

這兩個沒乙個是對的!!

copy constructor的構建操作(default memberwise initialization)

如果乙個類沒有提供乙個顯式的拷貝構造器,當乙個物件x1以另乙個相同類的物件x2為初值時,會以default memberwise initialization,也就是把每乙個內建的或者派生的資料成員的值拷貝到另個乙個物件,而其中的member class object並不會拷貝,而是以遞迴的方式bitwise initialization。(bitwise copy semantics 位逐次拷貝語意)

什麼時候不會展現出bitwise呢?

1.類內含有乙個成員物件,而後者含有乙個拷貝構造器時候(無論是自己設計的還是編譯器合成的)

2.當類繼承自乙個基類,而基類含有乙個拷貝構造器時。

3.當類宣告了乙個或者多個虛函式時。

4.當類派生自乙個繼承串鏈,其中有乙個虛基類時。

其中,1,2會將成員或基類的拷貝構造器呼叫操作安插在合成的拷貝構造器中,而3,4比較複雜,書的後面章節有繼續的介紹。

nrv(named return value)優化

x bar()

//優化之後

void bar(x&__result)

//如果不優化

void bar(x &__result)

可以減少拷貝構造的次數

x xx0(1024);//1號

x xx1=x(1024);//2號

x xx2=(x)1024;//3號

以上程式,2號,3號多了依次構造,還有依次析構來銷毀臨時物件,其中的步驟:

1.將暫時性的obejct設定為1024。

2.將暫時性的object以拷貝建構的方式作為explicit object初值

如果乙個類內含有乙個或乙個以上的虛函式,或有虛基類,那麼使用memcpy或者memset會使得被」編譯器產生的內部members「的初值被改寫。

member initialization list成員初始化列表

下面就4種情況必須使用成員初始化列表:

1.當初始化乙個reference member時。

2.當初始化乙個const member時。

3.當呼叫乙個base class的構造器,而它擁有一組引數時。

4.當呼叫乙個成員類的構造器,而它擁有一組引數時。

在這4種情況中,程式可以編譯,但是效率不高。

class word

}

list中的專案次序是由class中的成員宣告次序決定,不是由初始化列表中的排序次序決定

class x

//錯誤!i會先初始化

}

初始化成員列表的執行次序一定會在explicit user code之前!

深度探索C 物件模型筆記 第二章

explicit關鍵字能夠制止單參建構函式被當作型別轉換運算子.編譯器的隱式操作只是為了滿足編譯器本身的需求,而不是程式本身,乙個被編譯器隱式生成的預設建構函式,多數情況下對於程式本身來說是無用的.如果乙個類沒有任何建構函式,但類中的乙個非內建型別成員變數有預設建構函式,那麼這個類被隱式生成的預設建...

深度探索C 物件模型 第二章建構函式語意學

在使用c 時,常常會好奇或者抱怨,編譯器為我們做了什麼事呢?為什麼建構函式沒有為我初始化呢?為什麼我還要寫預設建構函式呢?2.1 default constructor 的構造操作 如果沒有宣告預設建構函式,編譯器會在需要的時候幫我們產生出來。為了避免在多個地方被需要導致重複,則編譯器將產生的建構函...

深度探索C 物件模型 第二章讀書筆記

1.如果設計者提供多個constructors,但其中都沒有default constructor呢?編譯器會擴張現在的每一次constructors,將 用以呼叫所有必要之default constructor 的程式 加進去。它不會合成乙個新的default constructor,因為其他由u...