Non-static data members

From cppreference.com
 
 
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements
Jump statements
Functions
function declaration
lambda function declaration
function template
inline specifier
exception specifications (deprecated)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
decltype specifier (C++11)
Specifiers
cv specifiers
storage duration specifiers
constexpr specifier (C++11)
auto specifier (C++11)
alignas specifier (C++11)
Initialization
Literals
Expressions
alternative representations
Utilities
Types
typedef declaration
type alias declaration (C++11)
attributes (C++11)
Casts
implicit conversions
const_cast conversion
static_cast conversion
dynamic_cast conversion
reinterpret_cast conversion
C-style and functional cast
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
class template
function template
template specialization
parameter packs (C++11)
Miscellaneous
Inline assembly
 

Non-static data members are the variables that 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[10] = {1,2}; // non-static data member with initializer (C++11)
    std::string s, *ps; // two non-static data members
    struct NestedS {
        std::string s;
    } d5, *d6; // two non-static data members of nested type
    char bit : 2; // two-bit bitfield
};

Any simple declarations are allowed, except

  • extern and register storage class specifiers are not allowed
  • thread_local storage class specifier is not allowed (but it is allowed for static data members)
  • incomplete types are not allowed: in particular, a class C cannot have a non-static data member of class 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.

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.

For non-union class types, members with the same 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.

[edit] Standard layout

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).

Two standard-layout struct types are called layout-compatible if they have the same number of non-static data members and the corresponding non-static data members, in declaration order, are themselves layout-compatible.

Two standard-layout struct types have a common initial sequence of non-static data members, if, for a sequence of one or more initial members (in order of declaration), the members have layout-compatible types.

Standard layout types have the following special properties:

  • If a standard-layout union holds two (or more) standard-layout structs as members, and these stucts 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.
  • A pointer to an object of standard-layout struct type can be reinterpret_cast to pointer to its first non-static data member, and vice versa. (padding is not allowed before the first data member). 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 struct

[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) (since C++11) Through a brace-or-equal initializer, which is simply an initializer included in the member declaration, which is used if the member is omitted in the member initializer list
struct S {
    int n = 7;
    std::string s{'a', 'b', 'c'};
    S() // copy-initializes n, list-initializes s
    { }
};

If a member has a brace-or-equal initializer and also appears in the member initialization list in a constructor, the brace-or-equal initializer is ignored.

#include <iostream>
int x = 0;
struct S {
    int n = ++x;
    S() {} // uses brace-or-equal initializer
    S(int arg) : n(arg) {} // uses member initializer list
};
int main()
{
    std::cout << x << '\n'; // prints 0
    S s1;
    std::cout << x << '\n'; // prints 1
    S s2(7);
    std::cout << x << '\n'; // prints 1
}

[edit] See also