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) |
C
cannot have a non-static data member of type C
, although it can have a non-static data member of type C&
(reference to C) or C*
(pointer to C);
| (since C++11) |
In addition, bit-field declarations are allowed.
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.
A class is considered to be standard-layout and to have properties described below if and only if it is a POD class. | (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 class (see standard-layout class for the list of requirements). | (since C++11) |
The common initial sequence of two standard-layout non-union class types is the longest sequence of non-static data members and bit-fields in declaration order, starting with the first such entity in each of the classes, such that.
| (since C++20) |
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:
T1
, it is permitted to read a non-static data member m
of another union member of non-union class type T2
provided m
is part of the common initial sequence of T1
and T2
(except that reading a volatile member through non-volatile glvalue is undefined). offsetof
may be used to determine the offset of any member from the beginning of a standard-layout class. 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. #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) |
If a reference member is initialized from its default member initializer (until C++20)a member has a default member initializer (since C++20) and a potentially-evaluated subexpression thereof is an aggregate initialization that would use that default member initializer, the program is ill-formed: 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++17) |
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
Feature-test macro | Value | Std | Comment |
---|---|---|---|
__cpp_nsdmi | 200809L | (C++11) | Non-static data member initializers |
__cpp_aggregate_nsdmi | 201304L | (C++14) | Aggregate classes with default member initializers |
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 80 | C++98 | all data members cannot have the same name as the name of the class (breaks C compatibility) | allow non-static data members share the class name if there is no user-declared constructor |
CWG 190 | C++98 | when determining layout compatibility, all members were considered | only consider non- static data members |
CWG 613 | C++98 | unevaluated uses of non-static data members not allowed | such uses are allowed |
CWG 645 | C++98 | it was unspecified whether bit-field and non-bit-field members are layout compatible | not layout compatible |
CWG 1397 | C++11 | class was regarded as complete in the default member initializers | default member init cannot trigger definition of default constructor |
CWG 1425 | C++98 | it was unclear whether a standard-layout object shares the same address with the first non-static data member or the first base class subobject | non-static data member if present, otherwise base class subobject if present |
CWG 1696 | C++98 | reference members could be initialized to temporaries (whose lifetime would end at the end of constructor) | 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 |
CWG 2583 | C++11 | common initial sequence did not consider alignment requirements | considered |
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) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/data_members