As I understand it, Empty Base-Class Optimization (EBO) should take effect when my type derives from a base class that has no data members or virtual functions. Under GCC and Clang, this is not happening. Here is a sample:
struct EmptyClass { };
struct SmallerClass : public EmptyClass {
long long int _x[2];
};
struct BiggerClass : public EmptyClass {
SmallerClass _sc;
};
struct BiggestClass : public EmptyClass {
BiggerClass _bc;
SmallerClass _sc;
};
I fully expected the size of BiggestClass
to be equal to the size of 4 long long int
s (32), but I noticed in the debugger that it was actually 48. Examining the AST in Clang (clang++ -cc1 -std=c++14 -fdump-record-layouts
) and GCC (g++ -std=c++14 -fdump-lang-all -c
) both showed me that EmptyClass
was taking space in each of the classes that included it (and for BiggestClass
, it occurs twice).
Here's the Clang AST output:
*** Dumping AST Record Layout
0 | struct EmptyClass (empty)
| [sizeof=1, dsize=1, align=1,
| nvsize=1, nvalign=1]
*** Dumping AST Record Layout
0 | struct SmallerClass
0 | struct EmptyClass (base) (empty)
0 | long long [2] _x
| [sizeof=16, dsize=16, align=8,
| nvsize=16, nvalign=8]
*** Dumping AST Record Layout
0 | struct BiggerClass
0 | struct EmptyClass (base) (empty)
8 | struct SmallerClass _sc
8 | struct EmptyClass (base) (empty)
8 | long long [2] _x
| [sizeof=24, dsize=24, align=8,
| nvsize=24, nvalign=8]
*** Dumping AST Record Layout
0 | struct BiggestClass
0 | struct EmptyClass (base) (empty)
8 | struct BiggerClass _bc
8 | struct EmptyClass (base) (empty)
16 | struct SmallerClass _sc
16 | struct EmptyClass (base) (empty)
16 | long long [2] _x
32 | struct SmallerClass _sc
32 | struct EmptyClass (base) (empty)
32 | long long [2] _x
| [sizeof=48, dsize=48, align=8,
| nvsize=48, nvalign=8]
So it seems not only is BiggestClass
larger than what I expected, BiggerClass
gets the size hit as well. It looks like nesting the classes removes the optimization.
What is the reasoning behind this removal of optimization, and is there a way around it that lets me compose these types with a common (empty) ancestor?