Difference between revisions of "cpp/language/data members"
(→Layout: P1847R4) |
(→Layout: mention standard-layout) |
||
Line 36: | Line 36: | ||
For non-{{rlp|union}} class types, {{rev inl|since=c++20|{{rlp|object#Subobjects|non-zero-sized}}}} members {{rev inl|until=c++11|not separated by an {{rlp|access|access specifier}}}}{{rev inl|since=c++11|with the same {{rlp|access|member access}}}} are always allocated so that the members declared later have higher addresses within a class object. Members {{rev inl|until=c++11|separated by an access specifier}}{{rev inl|since=c++11|with different access control}} are allocated in unspecified order (the compiler may group them together). | For non-{{rlp|union}} class types, {{rev inl|since=c++20|{{rlp|object#Subobjects|non-zero-sized}}}} members {{rev inl|until=c++11|not separated by an {{rlp|access|access specifier}}}}{{rev inl|since=c++11|with the same {{rlp|access|member access}}}} are always allocated so that the members declared later have higher addresses within a class object. Members {{rev inl|until=c++11|separated by an access specifier}}{{rev inl|since=c++11|with different access control}} are allocated in unspecified order (the compiler may group them together). | ||
|since2=c++23|rev2= | |since2=c++23|rev2= | ||
− | For non-{{rlp|union}} class types, {{rlp|object#Subobjects|non-zero-sized}} members are always allocated so that the members declared later have higher addresses within a class object. | + | For non-{{rlp|union}} class types, {{rlp|object#Subobjects|non-zero-sized}} members are always allocated so that the members declared later have higher addresses within a class object. Note that access control of member still affects the standard-layout property (see below). |
}} | }} | ||
Revision as of 05:55, 29 June 2021
Non-static data members are declared in a member specification of a class.
class S { int n; // non-static data member int& r; // non-static data member of reference type int a[2] = {1, 2}; // non-static data member with default member initializer (C++11) std::string s, *ps; // two non-static data members struct NestedS { std::string s; } d5; // non-static data member of nested type char bit : 2; // two-bit bitfield };
Any simple declarations are allowed, except
|
(since C++11) |
- incomplete types, abstract class types, and arrays thereof are not allowed: in particular, a class
C
cannot have a non-static data member of typeC
, although it can have a non-static data member of typeC&
(reference to C) orC*
(pointer to C); - a non-static data member cannot have the same name as the name of the class if at least one user-declared constructor is present;
|
(since C++11) |
In addition, bit field declarations are allowed.
Contents |
Layout
When an object of some class C
is created, each non-static data member of non-reference type is allocated in some part of the object representation of C
. Whether reference members occupy any storage is implementation-defined, but their storage duration is the same as that of the object in which they are members.
For non-union class types, non-zero-sized(since C++20) members not separated by an access specifier(until C++11)with the same member access(since C++11) are always allocated so that the members declared later have higher addresses within a class object. Members separated by an access specifier(until C++11)with different access control(since C++11) are allocated in unspecified order (the compiler may group them together). |
(until C++23) |
For non-union class types, non-zero-sized members are always allocated so that the members declared later have higher addresses within a class object. Note that access control of member still affects the standard-layout property (see below). |
(since C++23) |
Alignment requirements may necessitate padding between members, or after the last member of a class.
Standard layout
A class is considered to be standard-layout and to have properties described below if and only if it is a PODType. |
(until C++11) |
A class where all non-static data members have the same access control and certain other conditions are satisfied is known as standard layout type (see StandardLayoutType for the list of requirements). |
(since C++11) |
Two standard-layout non-union class types may have a common initial sequence of non-static data members and bit-fields, for a sequence of one or more initial members (in order of declaration), if the members have layout-compatible types either both declared with [[no_unique_address]]
attribute or declared without the attribute(since C++20), and if they are bit-fields, they have the same width.
struct A { int a; char b; }; struct B { const int b1; volatile char b2; }; // A and B's common initial sequence is A.a, A.b and B.b1, B.b2 struct C { int c; unsigned : 0; char b; }; // A and C's common initial sequence is A.a and C.c struct D { int d; char b : 4; }; // A and D's common initial sequence is A.a and D.d struct E { unsigned int e; char b; }; // A and E's common initial sequence is empty
Two standard-layout non-union class types are called layout-compatible if they are the same type ignoring cv-qualifiers, if any, are layout-compatible enumerations (i.e. enumerations with the same underlying type), or if their common initial sequence consists of every non-static data member and bit field (in the example above, A
and B
are layout-compatible)
Two standard-layout unions are called layout-compatible if they have the same number of non-static data members and corresponding non-static data members (in any order) have layout-compatible types.
Standard layout types have the following special properties:
- In a standard-layout union with an active member of non-union class type
T1
, it is permitted to read a non-static data memberm
of another union member of non-union class typeT2
providedm
is part of the common initial sequence ofT1
andT2
(except that reading a volatile member through non-volatile glvalue is undefined). - A pointer to an object of standard-layout class type can be reinterpret_cast to pointer to its first non-static non-bitfield data member (if it has non-static data members) or otherwise any of its base class subobjects (if it has any)(since C++11), and vice versa. In other words, padding is not allowed before the first data member of a standard-layout type. Note that strict aliasing rules still apply to the result of such cast.
- The macro offsetof may be used to determine the offset of any member from the beginning of a standard-layout class.
- In a standard-layout union with an active member of non-union class type
Member initialization
Non-static data members may be initialized in one of two ways:
struct S { int n; std::string s; S() : n(7) // direct-initializes n, default-initializes s { } };
2) Through a default member initializer, which is a brace or equals initializer included in the member declaration and is used if the member is omitted from the member initializer list of a constructor.
struct S { int n = 7; std::string s{'a', 'b', 'c'}; S() // default member initializer will copy-initialize n, list-initialize s { } }; If a member has a default member initializer and also appears in the member initialization list in a constructor, the default member initializer is ignored for that constructor. Run this code #include <iostream> int x = 0; struct S { int n = ++x; S() { } // uses default member initializer S(int arg) : n(arg) { } // uses member initializer }; int main() { std::cout << x << '\n'; // prints 0 S s1; // default initializer ran std::cout << x << '\n'; // prints 1 S s2(7); // default initializer did not run std::cout << x << '\n'; // prints 1 }
Members of array type cannot deduce their size from member initializers: struct X { int a[] = {1,2,3}; // error int b[3] = {1,2,3}; // OK }; Default member initializers are not allowed to cause the implicit definition of a defaulted default constructor for the enclosing class or the exception specification of that constructor: struct node { node* p = new node; // error: use of implicit or defaulted node::node() }; Reference members cannot be bound to temporaries in a default member initializer (note; same rule exists for member initializer lists) struct A { A() = default; // OK A(int v) : v(v) { } // OK const int& v = 42; // OK }; A a1; // error: ill-formed binding of temporary to reference A a2(1); // OK (default member initializer ignored because v appears in a constructor) // however a2.v is a dangling reference |
(since C++11) |
It is an error if a default member initializer has a subexpression that would execute aggregate initialization which would use the same initializer: struct A; extern A a; struct A { const A& a1{ A{a, a} }; // OK const A& a2{ A{} }; // error }; A a{a, a}; // OK |
(since C++14) |
Usage
The name of a non-static data member or a non-static member function can only appear in the following three situations:
this->
member access expressions that appear when a non-static member name is used in any of the contexts where this is allowed (inside member function bodies, in member initializer lists, in the in-class default member initializers).
struct S { int m; int n; int x = m; // OK: implicit this-> allowed in default initializers (C++11) S(int i) : m(i), n(m) // OK: implicit this-> allowed in member initializer lists { this->f(); // explicit member access expression f(); // implicit this-> allowed in member function bodies } void f(); };
struct S { int m; void f(); }; int S::*p = &S::m; // OK: use of m to make a pointer to member void (S::*fp)() = &S::f; // OK: use of f to make a pointer to member
struct S { int m; static const std::size_t sz = sizeof m; // OK: m in unevaluated operand }; std::size_t j = sizeof(S::m + 42); // OK: even though there is no "this" object for m
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 613 | C++98 | unevaluated uses of non-static data members not allowed | such uses are allowed |
CWG 1397 | C++11 | class was regarded as complete in the default member initializers |
default member init cannot trigger definition of default ctor |
CWG 1696 | C++98 | reference members could be initialized to temporaries (whose lifetime would end at the end of ctor) |
such init is ill-formed |
CWG 1719 | C++98 | differently cv-qualified types weren't layout-compatible | cv-quals ignored, spec improved |
CWG 2254 | C++11 | pointer to standard-layout class with no data members can be reinterpret_cast to its first base class |
can be reinterpret_cast to any of its base classes |
See also
classes | |
static members | |
non-static member functions | |
(C++11) |
checks if a type is a standard-layout type (class template) |
byte offset from the beginning of a standard-layout type to specified member (function macro) |