Edit: I just realized a much simpler way to ask this question:
Given the following two structs:
class Thing {public: int a; public: int b; public: int c;} class Thing {public: int a, private: int b; public: int c;}
Are the members
a
,b
, andc
guaranteed to be in the same order in memory for both of these definitions?
Let's say we have this C++ code in fileA.cpp
:
class Thing
{
public:
int a;
double num;
Thing()
{
b = 10;
}
float getB()
{
return b;
}
private:
float b;
Thing * other;
}
void doSomething(Thing thing);
int main()
{
Thing thing;
doSomething(thing);
std::cout << thing.b;
}
And let's say we have this code in fileB.cpp
:
class Thing
{
public:
int a;
double num;
Thing()
{
b = 10;
}
float getB()
{
return b;
}
float b;
private:
Thing * other;
}
void doSomething(Thing thing)
{
thing.b = 30;
}
Assuming the compiler wouldn't complain, would this code work as expected? That being, is the arrangement of a struct's data independent of whether or not certain components are public, private, or protected?
Edit: To make it more obvious, the only difference between the two definitions of Thing
is the fact that float b;
is private in fileA.cpp
but public in fileB.cpp
.
The standard makes no such guarantee. You have layout guarantees only for standard-layout classes:
A standard-layout class is a class that:
- has no non-static data members of type non-standard-layout class (or array of such types) or reference,
- has no virtual functions (10.3) and no virtual base classes (10.1),
- has the same access control (Clause 11) for all non-static data members,
- has no non-standard-layout base classes,
- either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and
- has no base classes of the same type as the first non-static data member.
(C++14, [class] ¶7)
If a class is standard-layout, its layout is well defined (and two standard layout classes that have a layout-compatible initial sequence may read each other's layout-compatible members through a union
).
However, here it is not the case, as you have different access specifiers throughout the class. In particular, it's explicitly stated that
The order of allocation of non-static data members with different access control is unspecified
(C++14, [class.mem] ¶13)
That being said, I never worked with any real world compiler that ever exploited this flexibility offered by the standard - every compiler I know uses the access specifiers for compile-time checks, but ignores them completely as far as members layout is concerned.