讓拷貝建構函數與賦值運算符共享邏輯看似直觀,實則隱藏效能陷阱。本文透過實測代碼揭示雙重初始化問題,給出最佳實踐。
// 寫法 1:拷貝建構呼叫賦值運算符
CFoo::CFoo(const CFoo& obj) { *this = obj; }
// 寫法 2:共用私有方法
void CFoo::CopyObj(const CFoo& rhs) { /* 複製邏輯 */ }
CFoo::CFoo(const CFoo& obj) { CopyObj(obj); }
CFoo& CFoo::operator=(const CFoo& rhs) { CopyObj(rhs); return *this; }
測試類別 `CMainClass` 包含 `CMember m_obj`:
CMainClass obj1;
CMainClass obj2(obj1); // 拷貝建構
輸出:
CMember: default ctor
CMainClass: copy-ctor
CMainClass: Operator=
CMember: Operator=
原因:拷貝建構先以預設建構函數初始化 `m_obj`,再呼叫 `operator=` 覆寫,導致雙重初始化。
// 拷貝建構:成員初始化列表直接呼叫成員的拷貝建構
CFoo::CFoo(const CFoo& rhs) : m_obj(rhs.m_obj) {}
// 賦值運算符:檢查自我賦值,逐成員賦值
CFoo& CFoo::operator=(const CFoo& rhs) {
if (this != &rhs) {
m_obj = rhs.m_obj;
// 其他成員...
}
return *this;
}
// 低效:預設建構 + 賦值
CFoo::CFoo() { m_obj = DEFAULT; }
// 高效:成員初始化列表
CFoo::CFoo() : m_obj(DEFAULT) {}