讀書筆記 深度探索C 物件模型(更新中

2021-07-04 02:26:58 字數 2617 閱讀 3192

下面通過幾個例子大概展示了c++物件記憶體布局在複雜的繼承關係中使用的策略。

開始之前,先來讀讀下面這段話

c++ standard 並不強制規定如 「base class subobjects 的排列次序」 或 「不同訪問層級的 data

member 的排列次序」這種瑣碎細節。它也不規定 virtual functions 或 virtual base classes

的實現細節。c++ standard 只是說:那些細節由各家廠商自定。

很坑爹吧? >_<

也因此, **執行得到的具體數值與系統環境和編譯器有關,這對**沒有影響。

lz使用mingw-gcc

// ***** 弱爆了的分界線 *****//

先來看第乙個case

// case 1

class x {};

class y: public

virtual x {};

class z: public

virtual x {};

class a: public y, public z {};

// sizeof x y z a -> 1 4 4 8

對於乙個空的物件,編譯器會為它至少分配乙個byte。所以 sizeof(x) = 1。

虛繼承會造成相應的負擔,在 derived class 中,這種負擔反應在某種形式的指標上。

gcc 的實現上,指標是指向虛表的。

指標是4位元組的,所以 y, z 的 size 至少是4位元組。

聰明的讀者一定會問,繼承來的基類子物件不是還有乙個 byte 嗎?

事實的確如此, 在一些機器上,sizeof(y) = 4(vptr) + 1(base subobject) + 3(alignment) = 8 byte

而像 gcc 這樣的編譯器, 為 empty virtual base class 提供特殊優化。

在這個策略下,乙個 empty virtual base class 被視為 derived class object 最開頭的一部分,

也就是說它並沒有花費任何的空間, 這就節省了上面所說的編譯器所插入的 1 byte。

所以 y, z 只包含乙個 vptr,size 就是 4 byte。

確定 a 的 size 時需要先解決乙個問題,x 在 a 中有幾個副本(儘管這裡可以優化)?

答案是, 只有 1 個

乙個 virtual base class subobject 只會 derived class 中存在乙份實體, 不管它在繼承體系中出現多少次!

所以 sizeof(a) 的計算方式:

- 共享的唯一的 x 實體,優化後為 0

- base class y 的大小, 減去因 x 而配置的大小。base class z 同。4 - 0 + 4 - 0 = 8

- class a 自己的大小: 0

- class a 的對齊: 0

則 sizeof(a) = 8

case 2 和 case 3 的計算方式相同, 作為 excercise 吧。

// case 2

// 與 case 1 唯一的區別是 x 有了乙個 char 型別的 data member

class x ;

class y: public

virtual x {};

class z: public

virtual x {};

class a: public y, public z {};

// sizeof x y z a -> 1 8 8 12

// case 3

class x ;

class y: public

virtual x {};

class z: public

virtual x {};

class a: public y, public z {};

// sizeof x y z a -> 1 8 8 12

對於 case 4, 並沒有用到虛繼承,所以也不會有相應的負擔。

這種情況,可以簡單理解為在 derived class 中直接放入 base class。

// case 4

class

x ;class

y: public

x {};

class

z: public

x {};

class

a: public

y, public

z {};

// sizeof x y z a -> 1 1 1 2

further reading:

c++ 多繼承和虛繼承的記憶體布局 詳細解釋了由gcc編譯器實現多繼承和虛繼承的物件的布局

《深度探索C 物件模型》讀書筆記(5)

純虛函式 在設計抽象基類時,需要注意以下幾點 1 不要將destructor宣告為pure virtual function 如果將destructor宣告為pure virtual function,則設計者一定得定義它。因為每乙個derived class destructor會被編譯器加以擴充...

《深度探索C 物件模型》讀書筆記(6)

物件的構造和解構 一般而言,我們會把object盡可能放置在使用它的那個程式區段附近,這樣做可以節省不必要的物件產生操作和銷毀操作。全域性物件 全域性物件的靜態初始化策略包括以下幾個步驟 1 為每乙個需要靜態初始化的物件產生乙個 sti 函式,內含必要的constructor呼叫操作或inline ...

讀書筆記 《深度探索c 物件模型》 (3)

第四章 function語意學 4.2 虛擬成員函式 a 單一繼承下的virtual function 乙個class只會有乙個virtual table 這個class自己定義的virtual function,它override了乙個可能存在的base class virtual functio...