首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 拷貝建構函式與指派運算子重載:陷阱、規則與最佳實務

     編輯:關於C++

拷貝建構函式觸發時機

  1. 函式參數為物件且傳值呼叫。
  2. 函式回傳物件且傳值回傳。
  3. 用物件初始化另一物件 (T t2 = t1;)。

此時編譯器執行位元拷貝 (bitwise copy),不會呼叫建構函式,導致資源管理型別 (含指標、檔案控制代碼、鎖) 出現雙重釋放、淺層複製等嚴重錯誤。

經典錯誤示範


class CTest {
public:
    CTest() { cout << "construct\n"; }
    ~CTest() { cout << "destruct\n"; }
};
void test(CTest obj) {}  // 傳值參數

int main() {
    CTest obj;
    test(obj);  // 輸出: construct, destruct, destruct
    // 僅呼叫 1 次建構、2 次解構!臨時物件未正確初始化
}

正確解法:自訂拷貝建構函式


class CTest {
public:
    int* data;
    CTest() : data(new int(0)) { cout << "construct\n"; }
    CTest(const CTest& other) : data(new int(*other.data)) {  // 深層複製
        cout << "copy construct\n";
    }
    ~CTest() { delete data; cout << "destruct\n"; }
};
// 輸出: construct, copy construct, destruct, destruct

指派運算子重載:初始化後的賦值

T t1, t2; t2 = t1; 不呼叫拷貝建構函式 (t2 已初始化),需重載 operator=:


CTest& operator=(const CTest& other) {
    if (this != &other) {           // 自我指派檢查
        delete data;                // 釋放舊資源
        data = new int(*other.data); // 深層複製
    }
    return *this;                   // 支援鏈式指派
}

三大法則 → 五大法則 (C++11)

函式C++98C++11+
解構函式必要必要
拷貝建構必要必要
拷貝指派必要必要
移動建構—必要 (資源竊取)
移動指派—必要

現代最佳實務

  1. 優先使用標準容器/智慧指標 (std::vector, std::unique_ptr) 讓編譯器自動生成正確的五大函式 (Rule of Zero)。
  2. 必須手寫資源管理類別時:成對出現 (拷貝建構+拷貝指派) 或 五個全寫 (移動語意)。
  3. operator= 必做:自我指派檢查、釋放舊資源、深層複製、回傳 *this。
  4. 拷貝建構函式參數用 const T&,避免無限遞迴。
  5. 考慮 noexcept 標記移動操作,啟用容器優化 (如 vector::resize 選用移動而非拷貝)。

編譯器預設行為的風險

雖然編譯器會合成預設拷貝/指派,但僅執行淺層逐成員拷貝。對管理動態資源的類別,預設行為幾乎必定錯誤。寧可顯式刪除 (=delete) 禁用拷貝,也不可依賴預設行為。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved