A given type of struct
always has the same size. This is a guarantee from the Standard. When you define a struct
, you are saying "I have an object of this size (sum of sizes of members + possible padding for alignment for each member), and they are to be in this order in memory (same order of member definitions in containing struct
definition)":
(N4296)
9.2
/12 [ Example: A simple example of a class definition is
struct tnode {
char tword[20];
int count;
tnode* left;
tnode* right;
};
which contains an array of twenty characters, an integer, and two pointers to objects of the same type. [...] -end example
/13 Nonstatic data members of a (non-union) class with the same access control (Clause 11) are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified (Clause 11). Implementation alignment requirements
might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).
Note the "with the same access control" qualifier. If your structure has a mix of data members with different access specifiers, the layout may not be what you might expect, other than the guarantee that given something like:
public:
some_type public_1;
private:
some_type private_1;
public:
some_type public_2;
public_2
will be at a higher address than public_1
. Beyond that - unspecified. private_1
could be at a lower or higher address.
Regarding your other question (asked in comments):
Would it be better to use a class instead of a struct then?
In C++, a struct
and class
are essentially the same, the only difference being that members (and inheritance) of a struct
are public
by default, whereas with a class
they are private
by default. This is made even clearer in a note and example from the Standard:
§3.1 Declarations and definitions [basic.def]
/3 [ Note: In some circumstances, C ++
implementations implicitly define the default constructor (12.1), copy
constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move assignment operator (12.8), or destructor (12.4) member functions. —end note ] [ Example: given
#include <string>
struct C {
std::string s; // std::string is the standard library class (Clause 21)
};
int main() {
C a;
C b = a;
b = a;
}
the implementation will implicitly define functions to make the definition of C equivalent to
struct C {
std::string s;
C() : s() { }
C(const C& x): s(x.s) { }
C(C&& x): s(static_cast<std::string&&>(x.s)) { }
// : s(std::move(x.s)) { }
C& operator=(const C& x) { s = x.s; return *this; }
C& operator=(C&& x) { s = static_cast<std::string&&>(x.s); return *this; }
// { s = std::move(x.s); return *this; }
~C() { }
};
—end example ]
Note that the example from the Standard uses a struct
rather than a class
to illustrate this point for non-POD structs
. This is even more clear when you consider that the definition of a struct
in the Standard is in Section 9 - "Classes."