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

C++ 對象模型:Copy Constructor 建構操作詳解 (第二章)

     編輯:關於C++

三種觸發複製構造的場景

  1. 顯式初始化:X xx = x;
  2. 函數參數傳值:void foo(X x); foo(xx);
  3. 函數返回值:X foo() { X xx; return xx; }

Default Memberwise Initialization (預設逐成員初始化)

若類未聲明複製構造函數,編譯器**不會**自動生成一個函數,而是在需要時進行「概念上的」逐成員複製:

  • 內建類型(指針、整數、數組等):直接位複製。
  • 類類型成員:遞歸進行逐成員初始化。

例如 String 類含 char* str; int len;,複製時僅複製指針值與長度,**不**深度複製字符串內容(淺拷貝)。若含 String 類型成員,則遞歸調用其複製構造。

Bitwise Copy Semantics (位逐次拷貝語意)

類滿足「位逐次拷貝」語意,當且僅當:

  1. 無用戶聲明的複製構造函數。
  2. 所有非靜態成員均為內建類型或滿足位逐次拷貝的類類型。
  3. 無虛函數、無虛基類。

此時編譯器**不合成**複製構造函數,直接對內存區塊進行 memcpy 式複製,極高效。

不滿足 Bitwise Copy Semantics 的四種情況(需合成複製構造)

  1. 含有**聲明了複製構造函數**的成員對象(或其基類)。
  2. 繼承自**有複製構造函數**的基類。
  3. 類**聲明了虛函數**(需初始化 vptr)。
  4. 類**繼承鏈中有虛基類**(需初始化虛基類指針/偏移)。

虛函數表指針 (vptr) 處理

合成複製構造函數會**顯式設置**新對象的 vptr 指向正確的虛函數表,而非直接複製來源對象的 vptr。這對於基類對象用派生類對象初始化(切割 slicing)至關重要:基類副本的 vptr 必須指向基類 vtable,否則虛函數調用會崩潰。

虛基類子對象處理

虛基類在派生類中位置不固定(運行期確定)。位逐次複製會破壞虛基類指針/偏移。合成複製構造函數會插入代碼重新初始化虛基類指針,確保後續訪問正確。

編譯器優化:抑制調用

若類滿足位逐次拷貝語意,編譯器會優化掉複製構造函數調用,直接內聯內存複製。若用戶提供了複製構造函數(即使語意相同),編譯器**必須**調用它(可能有副作用),無法優化。這是 C++ 性能與語意的權衡。

總結

  • 複製構造函數觸發場景:初始化、傳值參數、返回值。
  • 默認行為:逐成員初始化(淺拷貝指針,遞歸拷貝類成員)。
  • 位逐次拷貝語意類不合成複製構造,直接 memcpy。
  • 四種情況打破位逐次語意:成員/基類有複製構造、虛函數、虛基類。
  • 合成複製構造負責:調用成員/基類複製構造、初始化 vptr、修正虛基類指針。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved