3 the semantics of data
数据语义学
class X {};
class Y: virtual public X {};
class Z: virtual public virtual X {};
class A: public Y, public Z {};
空对象的大小是: sizeof(X) == 1
因为 class X 内有一个被编译器安插进去的 char, 这使得两个 class X object 得以在内存中配置独一无二的地址。(否则没办法区分)
sizeof(Y) == sizeof(Z) == 8 则需要考虑三个因素:
1、语言本身所造成的额外负担(overload) 当语言支持 virtual base classes 时, 就会导致一些额外负担(存放指针)。 在 derived class 中, 反映在某种形式的指针上, 它可能指向 virtual base class subobject 或者指向一个相关的表格, 表格中存放的可能是 virtual base class subobject 的地址, 也可能是其偏移量。
2、编译器对特殊情况所做出的优化处理 virtual base class X subobject 的 1 bytes 大小也出现在 class Y 和 Z 上。传统上它被放在 derived class 的固定部分的尾端。 而某些编译器会对 empty virtual base class 提供特殊之处支持。
3、 内存对齐机制 class Y 和 Z 的大小截至目前是 5 bytes。聚合的结构体大小会受到对齐的限制, 使它们有效的在内存中被存取。 大小是 4 bytes, 因此 class Y 和 Z 必须填补 3 bytes。 最终得到的结果就是 8 bytes。
一些编译器对 empty virtual base class提供了特殊处理:
一个 empty virtual base class 被视为 derived class object 最开始的一部分(也就是空,不存),并没有花费任何的额外空间。 这就节省了上述第二点的 1 bytes, 又从而变相节省了 3 bytes。
sizeof(A)大小:
如果 Y 和 Z 不是 virtual derived class X, 那么理论上 sizeof(A) == 16.
因为恰恰是 virtual derived, 所以 sizeof(A) 的值要从以下几点考虑:
Ⅰ、 一个virtual base class subobject只会在derived class中存在一份实例,不管继承体系中存在多少次。所以class X 实体,大小为 1 byte。
Ⅱ、Base class Y 的大小, 减去因 virtual base class X 而配置的大小, 结果是 4 bytes。 Base class Z 的算法亦同 。加起来是 8 bytes。
Ⅲ、class A 自己的大小是 0 byte.
Ⅳ、class A 的对对齐数量。前述三项总和,表示调整前的大小是 9 bytes,但是 class A 必须调至 4 bytes 的边界,填补 3 bytes。结果是 12 bytes。
若考虑编译器对 empty virtual base class提供了特殊处理:前述的 class X 实体的那 1 byte 将会被拿掉, 再去掉 3 bytes 的填补额, 于是 sizeof(A) == 8;
C++对象模型尽量以:空间优化、存取速度优化 考虑非静态数据成员。静态成员数据不影响对象的大小,静态成员数据只存储一份。

浙公网安备 33010602011771号