如何从空类继承时解释此sizeof结果

Nan*_*Hua 13 c++ inheritance struct

假设我有结构的以下C++定义.

struct Empty {};
struct Tmp : public Empty { int x; };
struct Tmp2 : public Empty { Tmp tmp;};
struct Tmp3 { Tmp tmp; };
Run Code Online (Sandbox Code Playgroud)

sizeof(Tmp3) == sizeof(Tmp) == 4,这是预期.但是,sizeof(Tmp2) == 8我想不出为什么......?你能解释一下吗?谢谢!

jua*_*nza 15

在这种情况下Tmp,允许空基类优化(EBCO)并且您的编译器正在应用它.

在这种情况下Tmp2,EBCO被禁用,因为数据成员Tmp2::tmp也是Empty.这是因为Tmp2有两个相同类型的子对象(基类子对象及其第一个数据成员).这些必须有不同的地址*.否则就不可能区分彼此.

这意味着基类有助于派生类的大小.


*来自1.8 C++对象模型:" 除非对象是零字段或零大小的基类子对象,否则该对象的地址是它占用的第一个字节的地址.两个不是位字段的对象可能具有相同的地址,如果其中一个是另一个的子对象,或者如果至少一个是零大小的基类子对象和它们是不同类型的;否则,它们应具有不同的地址. "

  • 为什么他们**必须**有不同的地址? (3认同)
  • @ixSci它在标准中指定.我添加了一个引用的脚注. (3认同)

Ulr*_*rdt 5

规则是两个相同类型的不同对象必须具有不同的地址,这也是空对象仍具有正大小的原因.由于这仅适用于相同类型的对象,因此两种不同类型可以共享存储,这是"空基类优化"的基础.

现在,您Tmp包含(作为基类)Empty子对象.此外,Tmp2有两个这样的子对象,一个通过其基类,另一个作为普通成员.此外,它有一个int.出于这个原因,你需要的不仅仅是一个更大的空间int,即sizeof (int) + 1至少.可能由于填充,它最终会有8个字节.

顺便说一句:考虑一个Tmp4,它继承自Tmp并且也包含一个Tmp.那个可能会有相同的大小Tmp2.

  • @ixSci - 相同类型的两个不同对象必须具有不同的地址,否则您无法区分它们.*不同*类型的对象,如结构及其第一个成员,可以具有相同的地址. (2认同)