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

C++ 對象模型第三章:Data Member 綁定與佈局

     編輯:關於C++

3.1 Data Member 綁定規則演進

早期「Member Rewriting Rule」

早期 C++ 編譯器(CFront)對 inline 成員函數的主體延遲到類定義結束才解析。導致:

extern float x;
class Point3d {
    float X() const { return x; } // 綁定到全域 x,而非成員 x!
    float x, y, z;
};

為規避此問題,形成兩種防禦風格:

  1. 所有數據成員前置聲明(放在類開頭)。
  2. 所有 inline 函數移至類外定義。

現代標準:Member Scope Resolution

C++ Standard 規定:inline 成員函數主體在類定義完整出現後才分析。因此上例中 X() 正確綁定到成員 x。
但若寫成:

extern int x;
class Point3d {
    float X() const { return x; } // 仍綁定全域 x,因類內尚未聲明成員 x
private:
    float x;
};

雖然標準保證「類定義完成後分析」,但名稱查找仍遵循「先查內部作用域,再查外層」,此時類內無 x,故綁定全域。最佳實踐:數據成員儘量前置。

3.2 Data Member 佈局

非靜態成員順序

  • 同一 access section(public/private/protected 塊)內,成員按聲明順序佈局,較晚聲明者地址較高。
  • 編譯器可插入填充位元組滿足對齊需求。
  • 靜態成員不佔用對象空間,存放於全局數據段。

多 Access Section 重排

標準允許編譯器將不同 access section 的成員自由重排,不保證聲明順序。但主流編譯器(MSVC, GCC, Clang)均按聲明順序連續佈局,section 間無額外開銷。

編譯器合成成員:vptr

  • 含 virtual 函數的類,編譯器在對象中插入 vptr 指向虛函數表。
  • 傳統放在所有用戶聲明成員之後;現代編譯器(如 MSVC)常放在對象最前端。標準不限制位置。

模板判斷成員相對順序

template 
char* access_order(D1 C::*m1, D2 C::*m2) {
    return (m1 < m2) ? "member 1 first" : "member 2 first";
}
// 用法:access_order(&Point3d::z, &Point3d::y);

利用成員指針比較大小可在運行期檢測佈局順序(需關閉優化)。

總結

成員綁定現遵循「類定義完成後分析」,但名稱查找仍依賴聲明位置;成員佈局在同 section 內保證聲明順序,section 間及 vptr 位置由編譯器決定。理解這些規則有助於編寫可移植、高效的 C++ 代碼,並能解讀對象內存佈局相關的底層問題。

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