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

深度探索 C++ 物件模型 (5):複製建構函式與位元級複製陷阱

     編輯:關於C++

複製建構函式何時需要

三種情況需以物件內容初始化另一同類別物件:

  1. 變數初始化:ClassA b = a;
  2. 函式參數傳值:void AddNew(CUser user); db.AddNew(user);
  3. 函式傳值返回:CUser GetUser(int id);

編譯器合成複製建構函式

類別未宣告複製建構函式時,編譯器隱含宣告並視需要合成。分為 trivial (位元級複製) 與 nontrivial (需逐項複製)。

位元級複製的災難案例

class Word {
public:
    Word(const char* s) : str(new char[strlen(s)+1]) { strcpy(str, s); }
    ~Word() { delete[] str; }
private:
    int cnt;
    char* str;
};

Word noun("lsmodel");
void foo() { Word verb = noun; } // 離開 foo() 時 verb 解構刪除 str,noun 成懸空指標

解決方案:實作深層複製的複製建構函式,或改用 String 類別 (具正確複製語意),讓編譯器合成正確呼叫 String 複製建構函式的版本。

四種非位元級複製情況 (需合成 nontrivial 複製建構函式)

  1. 類別宣告顯式複製建構函式。
  2. 基類有顯式複製建構函式。
  3. 類別宣告虛擬函式 (需重設 vptr 指向正確 vtable,而非複製來源的 vptr)。
  4. 繼承鏈含虛擬基類 (需設定虛擬基類指標/位移,執行成員級初始化)。

總結

當物件以另一物件為初值時,若類別涉及資源管理 (指標)、多態 (虛擬函式) 或虛擬繼承,位元級複製會導致嚴重錯誤。編譯器自動合成正確的複製建構函式處理 vptr 重設、虛擬基類指標調整與成員級初始化,確保物件語意正確性。

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