首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++默認拷貝構造函數合成規則:位拷貝語義與虛函數/虛繼承影響

     編輯:程式設計綜合問答

核心規則

編譯器**僅在需要時**合成拷貝構造函數,且行為取決於類結構:

代碼驗證

// 情況1:不合成(位拷貝)
class A { int x; char* p; }; // 簡單類型
A a1; A a2 = a1; // 直接內存複製,p指向同一地址(淺拷貝)

// 情況2:合成(成員級拷貝)
class B { 
    virtual void f();     // 虛函數 → 需複製vptr
    std::string s;        // 成員有拷貝構造
    int x;
};
B b1; B b2 = b1; // 合成拷貝構造:複製vptr、調用string拷貝、複製int

為什麼有虛函數必須合成?

  • 對象包含虛表指針(vptr),指向類的虛表。
  • 位拷貝會複製vptr指針值,**新對象vptr指向正確虛表**,看似無問題。
  • 但若類有虛基類,對象布局包含虛基類指針/偏移量,位拷貝會導致虛基子對象共享,破壞語義,**必須合成**處理偏移調整。
  • C++標準規定:有虛函數/虛基類/非平凡拷貝成員 → **非平凡拷貝構造** → 編譯器合成。

VS測試現象解釋

class B { public: int cc = 10; };
B b; B c = b; // 運行正常

此處B無虛函數、無虛基類、int為平凡類型 → **不合成拷貝構造**,使用**位拷貝**(逐字節複製cc),行為正確。若cc改為std::string,則合成拷貝構造調用string拷貝。

最佳實踐

  1. 遵循三/五/零法則:若需要自定義析構/拷貝/移動/賦值,通常五個都要寫(或用=default/=delete)。
  2. 管理資源的類**必須**定義拷貝語義(深拷貝/禁用拷貝/引用計數)。
  3. 使用=default顯式要求合成:B(const B&) = default;。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
類結構特徵合成行為語義
無虛函數、無虛基類、成員皆為內建類型/無自定義拷貝構造**不合成**位拷貝 - 逐字節複製內存
有虛函數 / 虛基類 / 成員有類類型且定義拷貝構造**合成**成員級拷貝 - 逐成員調用拷貝構造