大二時讀清華版C++教材,書中斬釘截鐵:「類無構造函數時編譯器自動生成默認構造函數」。直到讀到Lippman《Inside C++ Object Model》才知:這是廣為流傳的錯誤認知。Lippman直指兩大誤區:
編譯器僅在以下四種情況合成默認構造函數:
vfptr);vbptr)。class BaseClass { public: int a, b; /*無構造函數,無虛函數*/ };
class DerivedClass : public BaseClass { public: int c; };
sizeof(BaseClass)=8, sizeof(DerivedClass)=12 → 內存正常分配。
但直接讀取 baseClass.a 觸發Runtime Error:變量未初始化。
證明:編譯器未合成默認構造函數,成員含隨機垃圾值。
class BaseClass { public: int a, b; BaseClass() {} }; // 空體
程序正常運行,輸出 -858993460 -858993460(VC++未初始化填充值 0xCCCCCCCC)。
結論:用戶聲明的空構造函數也未初始化成員,但滿足了「類有構造函數」的語義,編譯器不再報錯。
class BaseClass { public: int a, b; virtual void show(){} }; // 無用戶構造函數
程序正常運行,sizeof(BaseClass)=12(+4字節vfptr)。
編譯器合成了默認構造函數,內部初始化vfptr指向虛函數表,但依然不初始化a、b。
class DerivedClass : virtual public BaseClass { public: int c; };
去掉 derivedClass.c 讀取 → Runtime Error。
改為虛繼承 → 程序正常,sizeof(DerivedClass)=16(含vbptr)。
證明:虛繼承強制編譯器合成構造函數初始化vbptr。
vfptr/vbptr/調用成員基類構造函數),不碰用戶數據成員。本文出自「酋長」博客,轉載請保留出處。