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

C++ 物件複製深度解析:拷貝建構函式、淺拷貝與深拷貝、臨時物件優化

     編輯:關於C++

拷貝建構函式基礎

當以同類別物件初始化新物件時呼叫:Test b = a;、函式傳值參數、函式回傳物件。若未自訂,編譯器產生預設拷貝建構函式 (逐成員複製)。


class Test {
public:
    Test(int v) : val(v) {}
    Test(const Test& other) : val(other.val) {  // 自訂拷貝建構函式
        cout << "拷貝建構函式被呼叫" << endl;
    }
private:
    int val;
};

參數必須為 const Test& (或 Test&),不可傳值 (否則無限遞迴)。

淺拷貝 vs 深拷貝

淺拷貝風險

類別含指標成員指向動態記憶體時,預設逐成員複製僅複製指標值,雙物件指向同一記憶體。解構時雙重 delete 導致崩潰。

深拷貝實作


class Internet {
public:
    Internet(char* n, char* a) {
        strcpy(name, n); strcpy(addr, a);
        cname = new char[strlen(n)+1];
        strcpy(cname, n);
    }
    Internet(const Internet& other) {  // 深拷貝
        strcpy(name, other.name);
        strcpy(addr, other.addr);
        cname = new char[strlen(other.cname)+1];  // 重新配置記憶體
        strcpy(cname, other.cname);
    }
    ~Internet() { delete[] cname; }
private:
    char name[20], addr[30];
    char* cname;  // 動態記憶體
};

核心:為指標成員配置新記憶體並複製內容,確保物件擁有獨立資源。

函式回傳物件與臨時物件


Internet Create() {
    Internet temp("Lab", "lab.com");
    return temp;  // 產生臨時物件
}

void main() {
    Internet a = Create();  // 呼叫拷貝建構函式初始化 a (可能被 RVO 優化)
}

編譯器可能執行 Return Value Optimization (RVO) 直接在呼叫端建構,省略臨時物件與拷貝。但語意上仍視為拷貝建構。

無名物件與拷貝省略


Internet a = Internet("Lab", "lab.com");  // 無名物件初始化
// 編譯器優化等同於:Internet a("Lab", "lab.com");
// 不會呼叫拷貝建構函式

C++ 標準允許編譯器省略無名物件的拷貝建構 (Copy Elision),直接建構目標物件。

參考綁定無名物件


const Internet& ref = Internet("Lab", "lab.com");  // 延長臨時物件壽命至參考結束
// 等價於:Internet temp("Lab", "lab.com"); const Internet& ref = temp;

非 const 左值參考無法綁定臨時物件 (C++11 起可用右值參考 Internet&&)。

最佳實務

  • 含資源類別 (指標、檔案控制代碼、Socket) 必須 實作深拷貝 (或禁用拷貝、實作移動語意 C++11)。
  • 遵循 Rule of Three/五:若需解構函式,幾乎一定需要拷貝建構/指派、移動建構/指派。
  • 優先使用標準容器/智慧指標 (std::string, std::vector, std::unique_ptr) 避免手動資源管理。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved