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++对象模型尽量以:空间优化、存取速度优化 考虑非静态数据成员。静态成员数据不影响对象的大小,静态成员数据只存储一份。

posted @ 2021-04-16 18:08  点|滴  阅读(6)  评论(0)    收藏  举报