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 emptyTwo 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 memberstruct 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