我们定义如下的类继承关系:
class X {};
class Y: public virtual X {};
class Z: public virtual X {};
class A: public Y, public Z {};
这是一个菱形继承,且所有类都未定义数据成员。对他们计算sizeof()
,书中给出以下结果:
Size of X: 1
Size of Y: 8
Size of Z: 8
Size of A: 12
X
是一个空类,但sizeof(X)
不等于0,而是1,这是编译器安插进去额一个byte,这保证了X
的实例在内存中拥有地址:
X a, b;
if(&a == &b) cerr << "yipes!" << endl;
而Y
和Z
的大小都是8。这个大小取决于三个因素
- 语言本身造成的overhead。C++支持virtual base class,会有一些额外负担。在派生类中,这个额外负担体现在某种形式的指针上,这个指针或者指向virtual base class subobject,或者指向一个表格,表格可能存放virtual base class subobject的地址,也可能存放其offset。该例中这个指针的大小为4字节(显然书中的环境是32位)。
- 编译器对于特殊情况提供的优化处理。
X
的一个字节也出现在Y
和Z
上,传统上会被放在子类固定部分的末尾。某些编译器会对empty virtual base class提供特殊支持,书中的结果并未体现这种优化。 - Alignment的限制。
Y
和Z
目前有了5个字节的大小。它们的大小还会受到alignment的限制,为了它们能够更有效率地在内存中被读取。如果alignment是4个字节,还需要额外三个字节来填补,最终得到8个字节。
Empty virtual base class已经被某些编译器支持了,它提供一个virtual interface,没有定义任何数据。一个empty virtual base class被视为子类对象最开头的部分,没有花费任何任何额外空间。因此可以节省上述三种情况中的第二种所造成的一个字节,由此第三点造成的alignment也不再需要。在这种模型下,Y
和Z
均为4个字节:
Size of X: 1
Size of Y: 4
Size of Z: 4
Size of A: 8
接下来考虑A
的大小。如果不考虑empty virtual base class优化,A
的大小为以下几项总和:
X
提供了一个字节。Y
的大小减去因virtual base classX
而配置的大小,结果是4字节,Z
同理,因此有8字节。A
自己的大小为0。- alignment要求。已经有了9字节,alignment到12字节。
因此A
的大小为12字节。
如果考虑empty virtual base class优化,1和4的overhead将不复存在,因此A
的大小为8字节。
最后一次更新于2022-06-05
0 条评论