Take this example
class A
{
public:
int a;
char b;
int c;
};
Every compiler (for x86, 32 or 64 bit) I see allocates 12 bytes for class A, instead of 9. So they are aligning b to the integer boundary or bus boundary you can say. My question is if this is in C++ standard to do so and if there are any compilers who does not do like that.
The C++ standard specifies that:
int is 4 bytes wide, then it requires an alignment of 1, 2 or 4 bytes, depending on the implementation).public) are all allocated in the order they're declaredSo no, the standard doesn't say exactly that the class should have a size of 12 bytes.
But it does say that b should be allocated after a, and that c should be allocated after b.
On a platform where int is 4 bytes wide, and requires 4-byte alignment, this leaves 12 bytes as the smallest valid size:
a takes the first 4 bytesb takes one bytec needs 4 bytes, but must be allocated on a 4-byte boundary. b ended one byte past such a boundary, so the next valid position to place c at is found by inserting 3 bytes of padding.So the total size of the class ends up being the size of the members (4 + 1 + 4 = 9) plus three bytes of padding, for a total of 12.
There is another rule which has no effect here, but which would matter if you had defined the members in the order a, c, b instead.
The containing class (A) inherits the alignment requirement from the strictest-aligned member object. That is, because it contains an int, it has the same alignment requirement as an int does. And because the object's total size must be a multiple of its alignment requirement, a class containing the members in the order a, b, c would still require 12 bytes of storage. It'd just shift the 3 bytes of padding to the end of the class, instead of between b and c.
However, in some other cases, reordering members in descending order of size can sometimes reduce the size of a class.
Suppose we'd had a class like this instead:
class B {
char a;
double b;
int c;
};
This would have required 24 bytes of storage (1 bytes for a, 8 byte for b, and 4 bytes for c, but then to ensure b ends up on an 8-byte boundary, we'd need 7 bytes of padding between a and b, and to ensure that the whole class ends up with a size that is a multiple of 8, we need another 4 bytes after c.
But reordering the members according to size, like this:
class B {
double b;
int c;
char a;
};
results in a class requiring only 16 bytes:
the same 1 + 4 + 8 bytes for the member objects themselves, but now c is already aligned on a 4-byte boundary (because it comes after b which ends on an 8-byte boundary), and a never needs any alignment, so the only alignment we need is to ensure that B has a size that is a multiple of 8. The members take 13 bytes, so we can add 3 bytes of padding, and the class ends up at 16 bytes, 33% smaller than the first version.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With