Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to explain this sizeof result when inheriting from an empty class

Suppose I have the following C++ definitions of structs.

struct Empty {};
struct Tmp : public Empty { int x; };
struct Tmp2 : public Empty { Tmp tmp;};
struct Tmp3 { Tmp tmp; };

The sizeof(Tmp3) == sizeof(Tmp) == 4, which is expected. However, sizeof(Tmp2) == 8, I can't think of why...? Could you help to explain? Thanks!

like image 376
Nan Hua Avatar asked Jun 27 '15 06:06

Nan Hua


2 Answers

In the case of Tmp, the empty base class optimization (EBCO) is permitted and your compiler is applying it.

In the case of Tmp2, the EBCO is disabled because the data member Tmp2::tmp is also an Empty. This is because Tmp2 has two sub-objects of the same type (the base class sub-object and its first data member). These must have distinct addresses*. Otherwise it would be impossible to distinguish one from the other.

This means the base class contributes to the derived class' size.


* From 1.8 The C++ Object Model: "Unless an object is a bit-field or a base class subobject of zero size, the address of that object is the address of the first byte it occupies. Two objects that are not bit-fields may have the same address if one is a subobject of the other, or if at least one is a base class subobject of zero size and they are of different types; otherwise, they shall have distinct addresses."

like image 158
juanchopanza Avatar answered Nov 15 '22 18:11

juanchopanza


The rule is that two different objects of the same type must have different addresses, which is also the reason that an empty object still has a positive size. Since this only applies to objects of the same type, two different types can share storage, which is the foundation of the "Empty Baseclass Optimization".

Now, your Tmp contains (as baseclass) an Empty subobject. Further, Tmp2 has two such subobjects, one via its baseclass, the other as plain member. Also, it has an int. For that reason, you need more space than just for the int, i.e. sizeof (int) + 1 at least. Probably due to padding, it then ends up with eight bytes.

BTW: Consider a Tmp4, which inherits from Tmp and also contains a Tmp. That one will probably have the same size as Tmp2.

like image 28
Ulrich Eckhardt Avatar answered Nov 15 '22 18:11

Ulrich Eckhardt