I'm playing with fdump-class-hierarchy compiler option but I don't know how I can understand the output. What does the "size", "align", "base size" and "base align" mean, and how these are counted? Thanks!
When the code is:
class A
{
public:
private:
double m_nothing;
int m_number;
};
The output is:
Class A
size=16 align=8
base size=16 base align=8
A (0x406c690) 0
But, if I change the class a little:
class A
{
public:
private:
int m_number;
double m_nothing;
};
the output will be:
Class A
size=16 align=8
base size=12 base align=8
A (0x406c690) 0
The
size
andalign
are the size and alignment of the class when used as complete type. That is, if you create objects whose complete type is that type (like defining variables of that type, or using that type withnew
).The size is simply the number of bytes it occupies. So
size=16
means when used as complete type, it always occupies 16 bytes.The alignment tells you where the object may be placed:
align=8
means the address of the object must be an integer multiple of 8.The
base size
andbase align
give the size and alignment in case the class is used as base class. The reason why they are different is that the C++ standard allows objects to use less padding when used as base class.So let's look specifically at your example (I'm assuming that you actually have the
int
before thedouble
in the first case). I'm also omitting thepublic
andprivate
because here they don't change anything (if you had both public or private data members, they could in principle change something, but I don't know if any compiler takes advantage of that). I'm also guessing the size and alignment ofint
anddouble
(actually the values I assume are pretty common choice, and explain the values you get).So in the first case (I assume) you have
Now
int
has size and alignment4
, and double has size and alignment8
.So let's do the job of the compiler and build our class.
First, we have
m_number
, which occupies 4 bytes. We have to put the members in the order given, som_number
goes at the beginning ofA
:Up to now, we have size 4 (the four bytes for the int), and alignment 4 (because int has alignment 4). But now we have to add a double (size and alignment 8). Since directly after the int, we are at (relative) address 4, we are not correctly aligned for the double, so we have to add 4 padding bytes (which I'll mark with
*
) to get to a multiple of 8. Thus we get for our class:Now, if the class is used as base class, we are finished. Thus we habe
base size=16
andbase align=8
(we need an alignment of 8 in order to get the double aligned correctly).For the complete object, there's another consideration: The standard demands that in arrays, the objects follow each other without a gap in between. That is, the first byte after the object must be correctly aligned for the next object. Which ultimately means that the size of the complete object has to be a multiple of its alignment.
Now the object layout we've found already fulfils that requirement. Therefore we can use it unchanged also for the complete object. Therefore we get
size=16
andalign=8
for the complete object.Now consider the case where the order is reversed:
Now we have to start with the
double
:Next, we have to add the
int
. As it turns out, the next free place is already correctly aligned for anint
, therefore we can just append it:Now for the use as base object, we are ready. As you can see, we only needed 12 bytes, therefore
base size=12
. Of course for thedouble
to be correctly aligned, the object again has to start at an address which is a multiple of 8. Therefore we havebase align=8
.However for the sue as complete object, we now find that the next address would be at position 12, which is not correctly aligned for the
double
member. Therefore we have to add padding bytes until we reach a correctly aligned address again:As you can see, now we need 16 bytes, thus
size=16
. We still havealign=8
due to the double.Note that the alignment requirement can dramatically affect the size of a class. Consider for example the following two types:
While both contain the same members,
S1
will with the sizes and alignments above have a total (non-base) size of 40, while the total size ofS2
will be just 24. Indeed, the objects of typeS1
will, as complete object, look likewhile those of type
S2
will look likeSo the bottom line is that members with the highest alignment requirement should always come first.
Also note that
sizeof
returns the size of complete objects, that is, what the class hierarchy dump callssize
.