The C++23 draft mandates that later non-static data members of a structure or class must have higher addresses. AFAIK earlier standards require this also partitially but there are rules when the compiler is allowed to reorder these data members. Can anyone here tell me which rules apply exactly when ?
From latest C++23 draft:
[expr.rel]
The result of comparing unequal pointers to objects is defined in terms of a partial order consistent with the following rules:
- If two pointers point to different non-static data members of the same object, or to subobjects of such members, recursively, the pointer to the later declared member is required to compare greater provided neither member is a subobject of zero size and their class is not a union.
The allocation order of non-static members is a necessary consequence of this rule. The rule is referred by a note:
[class.mem.general]
[Note 8: Non-variant non-static data members of non-zero size ([intro.object]) are allocated so that later members have higher addresses within a class object ([expr.rel]).
In C++11-20, prior to the proposal P1847, the rule was:
- If two pointers point to different non-static data members of the same object, or to subobjects of such members, recursively, the pointer to the later declared member is required to compare greater provided the two members have the same access control ([class.access]), neither member is a subobject of zero size, and their class is not a union.
- Otherwise, neither pointer is required to compare greater than the other
Pre C++23, compilers are allowed to re-order members with differing access control. Example:
struct s {
int a;
protected:
int b;
};
s ab;
// value of c is implementation dependent in C++20
// value of c is true in C++23
bool c = &ab.a < &ab.b;
Major compilers haven't actually used any other than declaration order.
C++03 was even more relaxed, although subtly:
[class.mem]
Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members separated by an access-specifier is unspecified (11.1).
[expr.rel]
- If two pointers point to non-static data members of the same object, or to subobjects or array elements of such members, recursively, the pointer to the later declared member compares greater provided the two members are not separated by an access-specifier label (11.1) and provided their class is not a union.
- If two pointers point to non-static data members of the same object separated by an access-specifier label (11.1) the result is unspecified.
struct A { char c; int x; }; class B : A { char d; };
The d
can now no longer be tucked into the padding. –
Funderburk struct A { int x; char c; };
–
Charlottcharlotta © 2022 - 2024 — McMap. All rights reserved.