第二章 構造函數語意學(the semantics of constructors)
2.1 Default Construcor 的建構操作
有四種情況,會導致“編譯器必須為未聲明constructor 之class 合成一個 Default constructor ”. C++ Stardand 把那些合成物稱為implicit nontrivial default constructor .被合成出來的的constructor 只能滿足編譯器(而非程序)的需求。它之所以能夠完成任務,是借著“調用member object 或 base class 的default constructor ”或是“為每一個object 初始化其virtual function 機制或virtual base class 機制” 而完成。至于沒有存在那四種情況而又沒有聲明任何constructor 的classes ,我們說它們擁有的是 implicit trivial constructors, 它們實際上并不會被合成出來。
在合成的default constructor 中,只有base class subobjects 和 member class objects h會被初始化。所有其它的nonstatic data member ,如整數、整數指針、整數數組等等都不會被初始化。這些初始化操作對程序而言或許有需要,但對編譯器則并非必要。如果程序需要一個“把某指針設為
C++新手一般有兩個常見的誤解:
1. 任何class 如果沒有定義default constructor ,就會被合成出一個來。
2. 編譯器合成出來的default constructor 會明確設定“class 內每一個data member 的默認值”。
2.2 Copy constructor 的建構操作
是一種特殊構造函數,具有單個形參,該形參(常用CONST修飾)是對該類類型的引用。當定義一個新對象并用一個同類型的對象對它進行初始化時,將顯式使用拷貝構造函數。當將該類型的對象傳遞給函數或從函數返回該類型的對象時,將隱式使用拷貝構造函數。
合成的拷貝構造函數:
即使我們定義了其他構造函數,也會合成拷貝構造函數。合成拷貝構造函數的行為是,執行逐個成員初始化(memberwise initialize),將新對象初始化為原對象的副本。
所謂“逐個成員”,指的是編譯器將現有對象的每個非static 成員,依次復制到正創建的對象。只有一個例外,每個成員的類型決定了復制該成員的含義。合成拷貝構造函數直接復制內置類型成員的值,類類型成員使用該類的拷貝構造函數進行復制。數組成員的復制是個例外。雖然一般不能復制數組,但如果一個類具有數組成員,則合成拷貝構造函數將復制數組。復制數組時合成拷貝構造函數將復制數組的每一個元素。
注意:按位拷貝不會分配新的內存空間而只是簡單地將該地址的值復制給另一個指針,所以就會出現兩個指針指向同一塊內存區域。
不要Bitwise Copy Semantics!
什么時候一個Class 不展現出“Bitwise Copy Semantics”呢?有四種情況:
1. 當class 內含一個member object 而后者的class 聲明有一個copy constructor 時
2. 當class 繼承自一個base class 而后者存在存在有一個copy constructor 時(再次強調,不論是被明確聲明或是被合成而得)。
3. 當class 聲明一個或多個 virtual function 時。
4. 當class 派生自一個繼承串鏈,其中有一個或多個virtual base classes時。