複製建構函數與重載賦值運算子是 C++ 物件語意的核心。本文系統總結其定義、調用時機、實作要點(深/淺拷貝)、細節規則與常見陷阱,並附完整程式碼驗證。
class CTest {
public:
CTest(); // 預設建構
~CTest(); // 解構
CTest(const CTest &); // 複製建構
CTest& operator=(const CTest &); // 重載賦值
};
class CTest {
public:
CTest() {}
~CTest() {}
CTest(const CTest &) { cout << "copy constructor." << endl; }
void operator=(const CTest &) { cout << "operator=" << endl; }
void Test(CTest test) {} // 傳值參數
CTest Test2() { CTest a; return a; } // 傳值回傳
void Test3(CTest &test) {} // 參考參數
CTest &Test4() { return *new CTest; } // 參考回傳
};
int main() {
CTest obj, obj1(obj); // 1. 宣告時初始化 → 複製建構
obj1 = obj; // 2. 已存在物件賦值 → 重載賦值
obj.Test(obj1); // 3. 傳值參數 → 複製建構(建立臨時物件)
CTest obj2 = obj.Test2(); // 4. 傳值回傳 → 複製建構(臨時物件) + 重載賦值
obj2.Test3(obj); // 5. 參考參數 → 無複製
CTest obj3 = obj.Test4(); // 6. 參考回傳 → 無複製(直接綁定)
}
宣告同時初始化 → 複製建構函數
已存在物件賦值 → 重載賦值運算子
class CTest {
wchar_t *pValue;
static const int MAXSIZE = 260;
public:
CTest(wchar_t *init) {
pValue = new wchar_t[MAXSIZE];
wcscpy_s(pValue, MAXSIZE, init);
}
~CTest() { delete[] pValue; pValue = nullptr; }
// 複製建構:配置新記憶體 + 逐字元複製
CTest(const CTest &t) {
pValue = new wchar_t[MAXSIZE];
wcscpy_s(pValue, MAXSIZE, t.pValue);
}
// 重載賦值:自賦值檢查 + 釋放舊記憶體 + 配置新 + 複製
CTest& operator=(const CTest &t) {
if (this == &t) return *this; // 自賦值防護
delete[] pValue; // 釋放舊資源
pValue = new wchar_t[MAXSIZE];
wcscpy_s(pValue, MAXSIZE, t.pValue);
return *this;
}
};
X&、const X&、volatile X&、const volatile X& 之一,且無其他參數或皆有預設值,即為複製建構函數。X(const X&) 與 X(X&);若僅有非 const 版,則無法以 const 物件初始化。X(const X&) 或 X(X&),視上下文而定。std::unique_ptr、std::string、std::vector 等 RAII 類別,避免手動管理動態記憶體。