編譯器僅在必要時才會合成預設建構子。若類別未宣告任何建構子,但符合特定條件,編譯器會生成一個 nontrivial(非平凡)的預設建構子,負責初始化基類子物件與成員類別物件。其他非靜態資料成員(如 int、指標)則不會被初始化。
複製建構子僅在類別不呈現「位元複製語意」時才會被合成。以下四種情況會導致非位元複製語意:
合成的複製建構子會遞迴執行 memberwise initialization,並插入必要的基類/成員複製建構子呼叫。
編譯器會優化物件回傳與初始化:
X xx0(1024); 單一建構子呼叫。X xx1 = X(1024); 與 X xx2 = (X)1024; 理論上涉及暫時物件建立、複製建構、解構,但優化後可直接建構於目標物件,省略複製動作。缺點:無法安全依賴複製建構子的副作用(如計數器),因執行次數不確定。
下列情況必須使用成員初始化列表:
使用初始化列表可避免「預設建構 → 暫時物件 → 指派 → 解構」的額外開銷,大幅提升效能。初始化順序依據類別內成員宣告順序,而非列表書寫順序,需特別留意相互依賴的初始化表達式。
// 使用者定義
Snow_White::Snow_White() : sneezy(1024) { mumble = 2048; }
// 編譯器擴張後
Snow_White::Snow_White() : sneezy(1024) {
dopey.Dopey::Dopey(); // 成員物件建構
sneezy.Sneezy::Sneezy();
bashful.Bashful::Bashful();
mumble = 2048; // 使用者程式碼
}