The size of any object or member subobject (unless [[no_unique_address]] – see below) (since C++20) is required to be at least 1 even if the type is an empty class type (that is, a class or struct that has no non-static data members), in order to be able to guarantee that the addresses of distinct objects of the same type are always distinct.
为了实现面向对象中的多态特性,大多数编译器都会将一个vptr插入到the most base class中,vptr指向vtable。关于vtable的相关知识,请参考我的这篇博文。正是因为vptr指针占用4个字节,并且基于empty base optimization原则,所以sizeof(Y) = 4。
Class X size=1 align=1 base size=0 base align=1 X (0x0x7f34c09cf5a0) 0 empty
Vtable for Y Y::_ZTV1Y: 3u entries 0 0u 8 (int (*)(...))0 16 (int (*)(...))(& _ZTI1Y)
VTT for Y Y::_ZTT1Y: 1u entries 0 ((& Y::_ZTV1Y) + 24u)
Class Y size=8 align=8 base size=8 base align=8 Y (0x0x7f34c08661a0) 0 nearly-empty vptridx=0u vptr=((& Y::_ZTV1Y) + 24u) X (0x0x7f34c09cf600) 0 empty virtual vbaseoffset=-24
Vtable for Z Z::_ZTV1Z: 3u entries 0 0u 8 (int (*)(...))0 16 (int (*)(...))(& _ZTI1Z)
VTT for Z Z::_ZTT1Z: 1u entries 0 ((& Z::_ZTV1Z) + 24u)
Class Z size=8 align=8 base size=8 base align=8 Z (0x0x7f34c0866208) 0 nearly-empty vptridx=0u vptr=((& Z::_ZTV1Z) + 24u) X (0x0x7f34c09cf660) 0 empty virtual vbaseoffset=-24
Construction vtable for Y (0x0x7f34c0866270 instance) in A A::_ZTC1A0_1Y: 3u entries 0 0u 8 (int (*)(...))0 16 (int (*)(...))(& _ZTI1Y)
Construction vtable for Z (0x0x7f34c08662d8 instance) in A A::_ZTC1A8_1Z: 3u entries 0 18446744073709551608u 8 (int (*)(...))0 16 (int (*)(...))(& _ZTI1Z)
Class A size=16 align=8 base size=16 base align=8 A (0x0x7f34c0878310) 0 vptridx=0u vptr=((& A::_ZTV1A) + 24u) Y (0x0x7f34c0866270) 0 nearly-empty primary-for A (0x0x7f34c0878310) subvttidx=8u X (0x0x7f34c09cf6c0) 0 empty virtual vbaseoffset=-24 Z (0x0x7f34c08662d8) 8 nearly-empty subvttidx=16u vptridx=24u vptr=((& A::_ZTV1A) + 48u) X (0x0x7f34c09cf6c0) alternative-path