Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/language/data members"

From cppreference.com
< cpp‎ | language
(The member initialization example doesn't use the right variables and doesn't list the correct expected output.)
m (Standard-layout: fix typo)
 
(47 intermediate revisions by 15 users not shown)
Line 1: Line 1:
 
{{title|Non-static data members}}
 
{{title|Non-static data members}}
 
{{cpp/language/classes/navbar}}
 
{{cpp/language/classes/navbar}}
Non-static data members are the variables that are declared in a {{rlp|class|member specification}} of a class.
+
Non-static data members are declared in a {{rlp|class|member specification}} of a class.
  
 
{{source|1=
 
{{source|1=
 
class S
 
class S
 
{
 
{
     int n;               // non-static data member
+
     int n;             // non-static data member
     int& r;               // non-static data member of reference type
+
     int& r;             // non-static data member of reference type
     int a[10] = {1, 2};   // non-static data member with initializer (C++11)
+
     int a[2] = {1, 2}; // non-static data member with default member initializer (C++11)
     std::string s, *ps;   // two non-static data members
+
     std::string s, *ps; // two non-static data members
     struct NestedS {
+
   
 +
     struct NestedS
 +
    {
 
         std::string s;
 
         std::string s;
     } d5, *d6;           // two non-static data members of nested type
+
     } d5;               // non-static data member of nested type
     char bit : 2;         // two-bit bitfield
+
   
 +
     char bit : 2;       // two-bit bitfield
 
};
 
};
 
}}
 
}}
  
 
Any {{rlp|declarations|simple declarations}} are allowed, except
 
Any {{rlp|declarations|simple declarations}} are allowed, except
* {{ltt|cpp/keyword/extern|extern}} and {{ltt|cpp/keyword/register|register}} storage class specifiers are not allowed;
+
* {{ltt|cpp/keyword/extern}} and {{ltt|cpp/keyword/register}} storage class specifiers are not allowed;
* {{ltt|cpp/keyword/thread local|thread_local}} storage class specifier is not allowed (but it is allowed for {{rlp|static}} data members);
+
{{rrev|since=c++11|
* {{rlp|incomplete type|incomplete types}} are not allowed: in particular, a class {{tt|C}} cannot have a non-static data member of type {{tt|C}}, although it can have a non-static data member of type {{tt|C&}} (reference to C) or {{tt|C*}} (pointer to C);
+
* {{ltt|cpp/keyword/thread_local}} storage class specifier is not allowed (but it is allowed for {{rlp|static}} data members);
 +
}}
 +
* {{rlp|incomplete type|incomplete types}}, {{rlp|abstract class|abstract class types}}, and arrays thereof are not allowed: in particular, a class {{tt|C}} cannot have a non-static data member of type {{tt|C}}, although it can have a non-static data member of type {{tt|C&}} (reference to C) or {{tt|C*}} (pointer to {{tt|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;
 
* 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;
* the {{rlp|auto|auto specifier}} cannot be used in a non-static data member declaration (although it is allowed for static data members that are {{rlp|static#Constant_static_members|initialized in the class definition}}).
+
{{rrev|since=c++11|
 +
* a {{rlp|auto|placeholder type specifier}} (i.e. {{c/core|auto}}{{rev inl|since=c++14|, {{c/core|decltype(auto)}}}}{{rev inl|since=c++17|, a class template name subject to {{rlp|class template argument deduction|deduction}}}}{{rev inl|since=c++20|, a {{rlp|constraints|constrained}} placeholder}}) cannot be used in a non-static data member declaration (although it is allowed for static data members that are {{rlp|static#Constant static members|initialized in the class definition}}).
 +
}}
  
In addition, {{rlp|bit_field|bit field declarations}} are allowed.
+
In addition, {{rlp|bit field|bit-field}} declarations are allowed.
  
 
===Layout===
 
===Layout===
 
When an object of some class {{tt|C}} is created, each non-static data member of non-reference type is allocated in some part of the object representation of {{tt|C}}. Whether reference members occupy any storage is implementation-defined, but their {{rlp|storage duration}} is the same as that of the object in which they are members.
 
When an object of some class {{tt|C}} is created, each non-static data member of non-reference type is allocated in some part of the object representation of {{tt|C}}. Whether reference members occupy any storage is implementation-defined, but their {{rlp|storage duration}} is the same as that of the object in which they are members.
  
For non-{{rlp|union}} class types, members with the same {{rlp|access|member access}} are always allocated so that the members declared later have higher addresses within a class object. Members with different access control are allocated in unspecified order (the compiler may group them together). Alignment requirements may necessitate padding between members, or after the last member of a class.
+
{{rrev multi|rev1=
 +
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=
 +
For non-{{rlp|union}} class types, {{rlp|object#Size|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).
 +
}}
  
===Standard layout===
+
Alignment requirements may necessitate padding between members, or after the last member of a class.
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 {{concept|StandardLayoutType}} for the list of requirements).
+
  
Two standard-layout non-union class types may have a ''common initial sequence'' of non-static data members{{rev inl|since=c++14| and bit-fields}}, for a sequence of one or more initial members (in order of declaration), if the members have layout-compatible types{{rev inl|since=c++14| and if they are bit-fields, they have the same width}}.
+
===Standard-layout===
 +
{{rrev multi
 +
|rev1=
 +
A class is considered to be ''standard-layout'' and to have properties described below if and only if it is a {{rlps|classes#POD class}}.
 +
|since2=c++11|rev2=
 +
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 {{rlpsd|classes#Standard-layout class}} for the list of requirements).
 +
}}
 +
 
 +
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
 +
{{rrev|since=c++20|
 +
* if {{c|__has_cpp_attribute(no_unique_address)}} is not {{c|0}}, neither entity is declared with {{attr|no_unique_address}} attribute,  
 +
}}
 +
* corresponding entities have layout-compatible types,
 +
* corresponding entities have the same {{rlp|object#Alignment|alignment requirements}}, and
 +
* either both entities are bit-fields with the same width or neither is a bit-field.
 
{{source|1=
 
{{source|1=
 
struct A { int a; char b; };
 
struct A { int a; char b; };
 
struct B { const int b1; volatile char b2; };  
 
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
 
// 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; };
 
struct C { int c; unsigned : 0; char b; };
 
// A and C's common initial sequence is A.a and C.c
 
// A and C's common initial sequence is A.a and C.c
 +
 
struct D { int d; char b : 4; };
 
struct D { int d; char b : 4; };
 
// A and D's common initial sequence is A.a and D.d
 
// A and D's common initial sequence is A.a and D.d
 +
 
struct E { unsigned int e; char b; };
 
struct E { unsigned int e; char b; };
 
// A and E's common initial sequence is empty
 
// 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 {{rev inl|since=c++14|ignoring cv-qualifiers, if any}}, are layout-compatible {{rlp|enum|enumerations}}, or if their ''common initial sequence'' consists of every non-static data member{{rev inl|since=c++14| and bit field}} (in the example above, {{tt|A}} and {{tt|B}} are layout-compatible)
+
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 {{rlp|enum|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, {{tt|A}} and {{tt|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.
 
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:
+
Standard-layout types have the following special properties:
{{rev begin}}
+
{{rev|until=c++14|
+
:* If a standard-layout {{rlp|union}} holds two (or more) standard-layout structs as members, and these structs have a common initial sequence of data members, it is well-defined to examine any member of that common initial sequence regardless of which member of the union is active.
+
}}
+
{{rev|since=c++14|
+
 
:* In a standard-layout union with an active member of non-union class type {{tt|T1}}, it is permitted to read a non-static data member {{tt|m}} of another union member of non-union class type {{tt|T2}} provided {{tt|m}} is part of the common initial sequence of {{tt|T1}} and {{tt|T2}} (except that reading a volatile member through non-volatile glvalue is undefined).
 
:* In a standard-layout union with an active member of non-union class type {{tt|T1}}, it is permitted to read a non-static data member {{tt|m}} of another union member of non-union class type {{tt|T2}} provided {{tt|m}} is part of the common initial sequence of {{tt|T1}} and {{tt|T2}} (except that reading a volatile member through non-volatile glvalue is undefined).
}}
+
:* A pointer to an object of standard-layout class type can be {{rlpt|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), and vice versa. In other words, padding is not allowed before the first data member of a standard-layout type. Note that {{rlp|reinterpret_cast#Type aliasing|strict aliasing}} rules still apply to the result of such cast.
{{rev end}}
+
:* The macro {{lc|offsetof}} may be used to determine the offset of any member from the beginning of a standard-layout class.
:* A pointer to an object of standard-layout struct type can be {{rlp|reinterpret_cast}} to pointer to its first non-static data member (if it has non-static data members) or otherwise its first base class subobject (if it has any), and vice versa. (padding is not allowed before the first data member). Note that [[cpp/language/reinterpret_cast#Type_aliasing|strict aliasing]] rules still apply to the result of such cast.
+
:* The macro {{lc|offsetof}} may be used to determine the offset of any member from the beginning of a standard-layout struct.
+
  
 
===Member initialization===
 
===Member initialization===
 
Non-static data members may be initialized in one of two ways:
 
Non-static data members may be initialized in one of two ways:
@1@ In the {{rlp|initializer_list|member initializer list}} of the constructor.
+
@1@ In the {{rlp|constructor|member initializer list}} of the constructor.
 
{{source|1=
 
{{source|1=
 
struct S
 
struct S
Line 71: Line 91:
 
     int n;
 
     int n;
 
     std::string s;
 
     std::string s;
     S() : n(7) // direct-initializes n, default-initializes s
+
     S() : n(7) {} // direct-initializes n, default-initializes s
    { }
+
 
};
 
};
 
}}
 
}}
  
{{rev begin}}
+
{{rrev|since=c++11|
{{rev |since=c++11|
+
@2@ Through a ''default member initializer'', which is a brace or equals {{rlp|initialization|initializer}} included in the member declaration and is used if the member is omitted from the member initializer list of a constructor.
@2@ Through a ''default member initializer'', which is simply a brace or equals {{rlp|initialization|initializer}} included in the member declaration, which is used if the member is omitted in the member initializer list
+
 
{{source|1=
 
{{source|1=
 
struct S
 
struct S
Line 84: Line 102:
 
     int n = 7;
 
     int n = 7;
 
     std::string s{'a', 'b', 'c'};
 
     std::string s{'a', 'b', 'c'};
     S() // copy-initializes n, list-initializes s
+
     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.
+
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.
{{source|1=
+
{{example|code=
 
#include <iostream>
 
#include <iostream>
  
Line 97: Line 114:
 
{
 
{
 
     int n = ++x;
 
     int n = ++x;
     S() { }                // uses default member initializer
+
     S() {}                // uses default member initializer
     S(int arg) : n(arg) { } // uses member initializer list
+
     S(int arg) : n(arg) {} // uses member initializer  
 
};
 
};
  
Line 104: Line 121:
 
{
 
{
 
     std::cout << x << '\n'; // prints 0
 
     std::cout << x << '\n'; // prints 0
     S s1;
+
     S s1;                   // default initializer ran
     std::cout << s1.n << '\n'; // prints 1
+
     std::cout << x << '\n'; // prints 1
     S s2(7);
+
     S s2(7);               // default initializer did not run
     std::cout << s2.n << '\n'; // prints 7
+
     std::cout << x << '\n'; // prints 1
 
}
 
}
 
}}
 
}}
Default member initializers are not allowed for {{rlp|bit field}} members.<!--cwg 1341-->
 
  
 +
{{rrev|until=c++20|
 +
Default member initializers are not allowed for {{rlp|bit field|bit-field}} members.
 +
}}
 
Members of array type cannot deduce their size from member initializers:
 
Members of array type cannot deduce their size from member initializers:
 
{{source|1=
 
{{source|1=
struct X {
+
struct X
  int a[] = {1,2,3}; // error
+
{
  int b[3] = {1,2,3}; // OK
+
    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 {{rlp|default constructor}} for the enclosing class or the exception specification of that constructor:
 +
{{source|1=
 +
struct node
 +
{
 +
    node* p = new node; // error: use of implicit or defaulted node::node()
 +
};
 
}}
 
}}
{{rev|since=c++14|
+
 
Reference members cannot be bound to temporaries in a default member initializer
+
Reference members cannot be bound to temporaries in a default member initializer (note; same rule exists for {{rlp|constructor#Explanation|member initializer lists}}):
 
{{source|1=
 
{{source|1=
 
struct A
 
struct A
 
{
 
{
     A() = default;         // OK
+
     A() = default;     // OK
     A(int v) : v(v) { }     // OK
+
     A(int v) : v(v) {} // OK
     const int& v = 42;     // OK
+
     const int& v = 42; // OK
 
};
 
};
 +
 
A a1;    // error: ill-formed binding of temporary to reference
 
A a1;    // error: ill-formed binding of temporary to reference
 
A a2(1); // OK (default member initializer ignored because v appears in a constructor)
 
A a2(1); // OK (default member initializer ignored because v appears in a constructor)
 
         // however a2.v is a dangling reference
 
         // however a2.v is a dangling reference
 +
}}
 
}}
 
}}
  
Reference members cannot be initialized with a default member initializer if it has a subexpression that would execute aggregate initialization which would use the same initializer:
+
 
 +
{{rrev|since=c++17|
 +
If {{rev inl|until=c++20|a reference member is initialized from its default member initializer}}{{rev inl|since=c++20|a member has a default member initializer}} and a {{rlp|expressions#Potentially-evaluated expressions|potentially-evaluated}} subexpression thereof is an {{rlp|aggregate initialization}} that would use that default member initializer, the program is ill-formed:
 
{{source|1=
 
{{source|1=
 
struct A;
 
struct A;
 
extern A a;
 
extern A a;
 +
 
struct A
 
struct A
 
{
 
{
     const A& a1{ A{a, a} }; // OK
+
     const A& a1{A{a, a}<!---->}; // OK
     const A& a2{ A{} };    // error
+
     const A& a2{A{}<!---->};    // error
 
};
 
};
A a{a, a};                 // OK
+
 
 +
A a{a, a};               // OK
 
}}
 
}}
 
}}
 
}}
{{rev end}}
 
  
 
===Usage===
 
===Usage===
 
The name of a non-static data member or a non-static member function can only appear in the following three situations:
 
The name of a non-static data member or a non-static member function can only appear in the following three situations:
@1@ As a part of class member access expression, in which the class either has this member or is derived from a class that has this member, including the implicit {{tt|this->}} member access expressions that appear when a non-static member name is used in any of the contexts where {{rlp|this}} is allowed (inside member function bodies, in member initializer lists, in the in-class default member initializers).
+
@1@ As a part of class member access expression, in which the class either has this member or is derived from a class that has this member, including the implicit {{c|this->}} member access expressions that appear when a non-static member name is used in any of the contexts where {{rlpt|this}} is allowed (inside member function bodies, in member initializer lists, in the in-class default member initializers).
 
{{source|1=
 
{{source|1=
 
struct S
 
struct S
Line 157: Line 189:
 
     int n;
 
     int n;
 
     int x = m;            // OK: implicit this-> allowed in default initializers (C++11)
 
     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
 
     S(int i) : m(i), n(m) // OK: implicit this-> allowed in member initializer lists
 
     {
 
     {
Line 162: Line 195:
 
         f();              // implicit this-> allowed in member function bodies
 
         f();              // implicit this-> allowed in member function bodies
 
     }
 
     }
 +
   
 
     void f();
 
     void f();
 
};
 
};
Line 169: Line 203:
 
struct S
 
struct S
 
{
 
{
  int m;
+
    int m;
  void f();
+
    void f();
 
};
 
};
 +
 
int S::*p = &S::m;      // OK: use of m to make a pointer to member
 
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
 
void (S::*fp)() = &S::f; // OK: use of f to make a pointer to member
 
}}
 
}}
  
{{rev begin}}
+
@3@ (for data members only, not member functions) When used in {{rlp|expressions#Unevaluated expressions|unevaluated operands}}.
{{rev|since=c++03|
+
@3@ In unevaluated operands.
+
 
{{source|1=
 
{{source|1=
 
struct S
 
struct S
 
{
 
{
  int m;
+
    int m;
  static const std::size_t sz = sizeof m; // OK: m in unevaluated operand
+
    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
 
std::size_t j = sizeof(S::m + 42); // OK: even though there is no "this" object for m
 
}}
 
}}
}}
+
@@ Notes: such uses are allowed via the resolution of {{cwg|613}} in {{wg21|N2253}}, which is treated as a change in C++11 by some compilers (e.g. clang).
{{rev end}}
+
 
 +
===Notes===
 +
{{ftm begin|core=1|std=1|comment=1}}
 +
{{ftm|value=200809L|std=C++11|__cpp_nsdmi|[[#Member initialization|Non-static data member initializers]]}}
 +
{{ftm|value=201304L|std=C++14|__cpp_aggregate_nsdmi|[[cpp/language/aggregate_initialization|Aggregate classes]] with [[#Member initialization|default member initializers]]}}
 +
{{ftm end}}
  
 
===Defect reports===
 
===Defect reports===
 
{{dr list begin}}
 
{{dr list begin}}
{{dr list item|wg=cwg|dr=613|std=C++03|before=unevaluated uses of non-static data members not allowed|after=such uses are allowed}} <!-- gcc in particular supports it in C++03 more and defended this support as intentional in bug report 65890 -->
+
{{dr list item|wg=cwg|dr=80|std=C++98|before=all data members cannot have the same name<br>as the name of the class (breaks C compatibility)|after=allow non-static data members<br>share the class name if there is<br>no user-declared constructor}}
{{dr list item|wg=cwg|dr=1696|std=C++14|before=reference members could be initialized to temporaries (whose lifetime would end at the end of ctor)|after=such init is ill-formed}}
+
{{dr list item|wg=cwg|dr=190|std=C++98|before=when determining layout compatibility,<br>all members were considered|after=only consider non-<br>static data members}}
{{dr list item|wg=cwg|dr=1719|std=C++14|before=differently cv-qualified types weren't layout-compatible|after=cv-quals ignored, spec improved}}
+
{{dr list item|wg=cwg|dr=613|std=C++98|before=unevaluated uses of non-static data members not allowed|after=such uses are allowed}} <!-- gcc in particular supports it in C++03 more and defended this support as intentional in bug report 65890 -->
 +
{{dr list item|wg=cwg|dr=645|std=C++98|before=it was unspecified whether bit-field and<br>non-bit-field members are layout compatible|after=not layout compatible}}
 +
{{dr list item|wg=cwg|dr=1397|std=C++11|before=class was regarded as complete<br>in the default member initializers|after=default member init cannot trigger<br>definition of default constructor}}
 +
{{dr list item|wg=cwg|dr=1425|std=C++98|before=it was unclear whether a standard-layout object<br>shares the same address with the first non-static<br>data member or the first base class subobject|after=non-static data member<br>if present, otherwise base<br>class subobject if present}}
 +
{{dr list item|wg=cwg|dr=1696|std=C++98|before=reference members could be initialized to temporaries<br>(whose lifetime would end at the end of constructor)|after=such init is ill-formed}}
 +
{{dr list item|wg=cwg|dr=1719|std=C++98|before=differently cv-qualified types weren't layout-compatible|after=cv-quals ignored, spec improved}}
 +
{{dr list item|wg=cwg|dr=2254|std=C++11|before=pointer to standard-layout class with no data<br>members can be reinterpret_cast to its first base class|after=can be reinterpret_cast<br>to any of its base classes}}
 +
{{dr list item|wg=cwg|dr=2583|std=C++11|before=common initial sequence did not<br>consider alignment requirements|after=considered}}
 +
{{dr list item|wg=cwg|dr=2759|std=C++20|before=common initial sequence could include<br>members declared {{attr|no_unique_address}}|after=they are not included}}
 
{{dr list end}}
 
{{dr list end}}
  
 
===See also===
 
===See also===
*{{rlp|classes|classes}}
+
{{dsc begin}}
*{{rlp|static|static data members}}
+
{{dsc|{{rlp|classes|classes}}}}
*{{rlp|member_functions|member functions}}
+
{{dsc|{{rlp|static|static members}}}}
*{{lc|std::is_standard_layout}}
+
{{dsc|{{rlp|member functions|non-static member functions}}}}
*{{lc|offsetof}}
+
{{dsc inc|cpp/types/dsc is_standard_layout}}
 +
{{dsc inc|cpp/types/dsc offsetof}}
 +
{{dsc end}}
 +
 
 +
{{langlinks|es|ja|ru|zh}}

Latest revision as of 13:29, 19 January 2024

 
 
C++ language
General topics
Flow control
Conditional execution statements
if
Iteration statements (loops)
for
range-for (C++11)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications (until C++17*)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
explicit (C++11)
static

Special member functions
Templates
Miscellaneous
 
 

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

  • thread_local storage class specifier is not allowed (but it is allowed for static data members);
(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 type C, although it can have a non-static data member of type C& (reference to C) or C* (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

[edit] 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.

[edit] Standard-layout

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

  • if __has_cpp_attribute(no_unique_address) is not 0, neither entity is declared with [[no_unique_address]] attribute,
(since C++20)
  • corresponding entities have layout-compatible types,
  • corresponding entities have the same alignment requirements, and
  • either both entities are bit-fields with the same width or neither is a bit-field.
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 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).
  • 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), 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.

[edit] Member initialization

Non-static data members may be initialized in one of two ways:

1) In the member initializer list of the constructor.
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
}

Default member initializers are not allowed for bit-field members.

(until C++20)

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)

[edit] Usage

The name of a non-static data member or a non-static member function can only appear in the following three situations:

1) As a part of class member access expression, in which the class either has this member or is derived from a class that has this member, including the implicit 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();
};
2) To form a pointer to non-static member.
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
3) (for data members only, not member functions) When used in unevaluated operands.
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
Notes: such uses are allowed via the resolution of CWG issue 613 in N2253, which is treated as a change in C++11 by some compilers (e.g. clang).

[edit] Notes

Feature-test macro Value Std Feature
__cpp_nsdmi 200809L (C++11) Non-static data member initializers
__cpp_aggregate_nsdmi 201304L (C++14) Aggregate classes with default member initializers

[edit] 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 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
CWG 2759 C++20 common initial sequence could include
members declared [[no_unique_address]]
they are not included

[edit] See also

classes
static members
non-static member functions
checks if a type is a standard-layout type
(class template) [edit]
byte offset from the beginning of a standard-layout type to specified member
(function macro) [edit]