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

C++ 類別物件深拷貝與淺拷貝建構函式詳解

     編輯:關於C++

類別物件複製涉及拷貝建構函式。若未自訂,編譯器提供預設版本執行「成員逐一複製」(淺拷貝)。當類別管理動態資源(堆記憶體、檔案控制代碼等)時,淺拷貝會導致資源擁有權混淆、雙重釋放崩潰,必須實作深拷貝。

預設拷貝建構函式

class Test {
    int p1;
public:
    Test(int t) : p1(t) {}
    // 編譯器隱式產生:Test(const Test& rhs) : p1(rhs.p1) {}
};

對純量成員(int、double 等)足夠,但指標成員僅複製位址,雙方指向同一塊記憶體。

深拷貝實作範例

class Internet {
    char name[20], address[30];
    char* cname; // 動態配置
public:
    Internet(const char* n, const char* a) {
        strcpy(name, n); strcpy(address, a);
        cname = new char[strlen(n)+1];
        strcpy(cname, n);
    }
    // 深拷貝建構函式
    Internet(const Internet& src) {
        strcpy(name, src.name);
        strcpy(address, src.address);
        cname = new char[strlen(src.name)+1]; // 重新配置
        strcpy(cname, src.name);
    }
    ~Internet() { delete[] cname; }
};

關鍵:在拷貝建構函式中為指標成員 new 新記憶體並複製內容,析構函式釋放自有記憶體,確保各物件擁有獨立資源。

淺拷貝風險示範

若拷貝建構函式僅執行 cname = src.cname,兩物件共享同一記憶體區塊。第一個物件銷毀時 delete[] 釋放記憶體,第二個物件銷毀時對已釋放記憶體再次 delete[],導致未定義行為(通常崩潰)。

函數傳回物件與暫時物件

函數以值傳回類別物件會產生暫時物件,觸發拷貝建構函式。編譯器優化(RVO/NRVO)可能省略拷貝,但語意上仍視為拷貝發生。

無名物件特殊規則

  • Internet a = Internet(...);:編譯器優化為直接建構 a,不呼叫拷貝建構函式。
  • Internet& a = Internet(...);:參考綁定暫時物件,延長其生命週期至參考離開作用域,同樣不呼叫拷貝建構函式(但析構時機不同)。

定義總結

  • 淺拷貝:複製成員位址/值,不複製所指資源。
  • 深拷貝:配置新資源並複製內容,各物件獨立擁有資源。
  • 原則:類別擁有資源(堆記憶體、檔案、Socket 等)時,必須自訂拷貝建構函式、複製指派運算子與析構函式(三大法則),C++11 後擴展為五大法則(含移動建構/指派)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved