在 C++ 程式設計中,當類別內部包含指標成員或動態分配的資源時,預設的「淺拷貝」行為往往會導致嚴重的記憶體錯誤,例如雙重釋放或記憶體洩漏。這就是「三大法則」的由來:如果類別需要自定義解構函數、複製建構函數或賦值運算符,通常這三者都需要自定義。
雖然兩者都是用現有物件 B 來初始化或賦值給物件 A,但它們的應用場景截然不同:
在物件 A 尚未存在 時被調用,屬於初始化過程。
CTemp a(b); // 標準 C++ 風格初始化
CTemp a = b; // 等號形式初始化,本質仍是複製建構(非賦值)
此時 A 還未構造完成,直接從 B 複製資料建立新個體。
在物件 A 已經存在 並完成預設構造後被調用,屬於賦值操作。
CTemp a; // 先預設構造
a = b; // 再賦值,調用 operator=
此時必須先釋放 A 原有的資源,再從 B 深拷貝資料,最後返回 *this 以支援鏈式賦值。
自定義時務必實作「深拷貝」:為指標成員分配新記憶體並複製內容。賦值運算符還需加入自賦值檢查(if (this != &rhs)),避免釋放自身資源導致崩潰。
C++11 起引入移動語意,配合「五大法則」或直接使用智慧指標(unique_ptr, shared_ptr)與標準容器,往往能讓編譯器自動生成正確的拷貝/移動行為,減少手動管理錯誤。