I was going through great articles on C++ POD, Trivial and Standard Layout classes One property I haven't clearly understood about standard layout is the following:-
A standard layout has no base classes of the same type as the first
non-static data member
So the following will not be a Standard Layout as it has the first member same as the base class
struct NonStandardLayout3 : StandardLayout1 {
StandardLayout1 x; // first member cannot be of the same type as base
};
But performance-wise and property-wise how is the above struct any different than
struct StandardLayout5 : StandardLayout1 {
int x;
StandardLayout1 y; // can have members of base type if they're not the first
};
which is the correction of the one above this.
Trivial typesWhen a class or struct in C++ has compiler-provided or explicitly defaulted special member functions, then it is a trivial type. It occupies a contiguous memory area. It can have members with different access specifiers. In C++, the compiler is free to choose how to order members in this situation.
A standard-layout type is a type with a simple linear data structure and access control that can easily be used to communicate with code written in other programming languages, such as C, either cv-qualified or not.
A POD type (which stands for Plain Old Data type) is a type whose characteristics are supported by a data type in the C language, either cv-qualified or not. This includes scalar types, POD classes and arrays of any such types.
A trivial type is a type whose storage is contiguous (trivially copyable) and which only supports static default initialization (trivially default constructible), either cv-qualified or not. It includes scalar types, trivial classes and arrays of any such types.
The reason is that standard layout types effectively mandate the "empty base class optimization" where base classes with no data members take up no space and have the same address as the first data member (if any) of the derived class.
However, attempting doing this when the base class has the same type as the first data member violates the C++ memory model which requires that distinct objects of the same type must have distinct addresses.
From ISO/IEC 14882:2011 1.8 [intro.object]/6:
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
effectively mandating the empty base class, 9.2 [class.mem] /20:
A pointer to a standard-layout struct object, suitably converted using a
reinterpret_cast
, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa.
It would be impossible for the following types (Type1
and Type2
) to be layout-compatible (although they would otherwise be standard-layout classes) without this restriction.
struct S1 {};
struct S2 {};
struct Type1 : S1 {
S1 s;
int k;
};
struct Type2 : S1 {
S2 s;
int m;
};
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