Namespaces
Variants
Views
Actions

Member initializer list

From cppreference.com
< cpp‎ | language
Revision as of 06:59, 24 September 2013 by Cubbi (Talk | contribs)

 
 
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
friend specifier
initializer lists
Class-specific function properties
Special member functions
Templates
class template
function template
template specialization
parameter packs (C++11)
Miscellaneous
Inline assembly
 

In the definition of a constructor of a class, specifies initializers for direct and virtual base subobjects and non-static data members. ( Not to be confused with std::initializer_list )

Contents

Syntax

Appears as part of function definition syntax, for class constructors only, as the first part of the function body (before the opening brace of the compound statement)

The first character is the colon :, followed by the comma-separated list of one or more member-initializers, each of which has the following syntax

class-or-identifier ( expression-list(optional) ) (1)
class-or-identifier brace-init-list (2) (since C++11)
parameter-pack ... (3) (since C++11)
1) Initializes the base or member named by class-or-identifier using direct initialization or, if expression-list is empty, value- or default-initialization
2) Initializes the base or member named by class-or-identifier using list-initialization or aggregate-initialization
3) Initializes multiple bases using a pack expansion
class-or-identifier - any identifier, class name, or decltype expression that names a non-static data member, a direct or virtual base, or (for delegating constructors) the class itself
expression-list - possibly empty, comma-separated list of the parameters to pass to the constructor of the base or member
brace-init-list - brace-enclosed list of comma-separated initializers and nested braced-init-lists
parameter-pack - name of a variadic template parameter pack

Explanation

Before the compound statement that forms the function body of the constructor begins executing, initialization of all direct bases, virtual bases, and non-static data members is finished. Member initializer list is the place where non-default initialization of these objects can be specified and, for members that cannot be default-initialized, such as members of reference and const-qualified types, member-initializers are required.

The initializers where class-or-identifier names a virtual base class are ignored during execution of constructors of any class that is not the most derived class of the object that's being constructed.

Names that appear in expression-list or brace-init-list are evaluated in scope of the constructor:

class X {
    int a, b, i, j;
public:
    const int& r;
    X(int i): r(a), // initializes X::r to refer to X::a
              b(i), // initializes X::b to the value of the parameter i
              i(i), // initializes X::i to the value of the parameter i
              j(this->i) // initializes X::j to the value of X::i
    { }
};

Member functions (including virtual member functions) can be called from member initializers, but the behavior is undefined if not all direct bases are initialized at that point.

For virtual calls (if the bases are initialized), the same rules apply as the rules for the virtual calls from constructors and destructors: virtual member functions behave as if the dynamic type of *this is the class that's being constructed (dynamic dispatch does not propagate down the inheritance hierarchy) and virtual calls (but not static calls) to pure virtual member functions are undefined behavior.

If a non-static data member has an in-class brace-or-equal initializer and also appears in a member initializer list, then member initializer list is executed and brace-or-equal initializer is ignored:

struct S {
    int n = 42;
    S() : n(7) {} // will set n to 7, not 42
};
(since C++11)

Delegating constructor

If the name of the class itself appears as class-or-identifier in the member initializer list, then the list must consist of that one member initializer only; such constructor is known as the delegating constructor, and the constructor selected by the only member of the initializer list is the target constructor

In this case, the target constructor is selected by overload resolution and executed first, then the control returns to the delegating constructor and its body is executed.

Delegating constructors cannot be recursive.
(since C++11)

Initialization order

The order of member initializers in the list is irrelevant: the actual order of initialization is as follows:

1) If the constructor is for the most-derived class, virtual base classes are initialized in the order in which they appear in depth-first left-to-right traversal of the base class declarations (left-to-right refers to the appearance in base-specifier lists)
2) Then, direct base classes are initialized in left-to-right order as they appear in this class's base-specifier list
3) Then, non-static data members are initialized in order of declaration in the class definition.
4) Finally, the body of the constructor is executed

(Note: if initialization order was controlled by the appearance in the member initializer lists of different constructors, then the destructor wouldn't be able to ensure that the order of destruction is the reverse of the order of construction)

Example

struct Class : public Base
{
    int x;
    int y;
 
    Class ( int x )
      : Base ( 123 ), // initialize base class
        x ( x ),      // x (member) is initialized with x (parameter)
        y ( 0 )       // y initialized to 0
    {}                // empty constructor body
 
    Class ( double a )
      : y ( a+1 ),
        x ( y ) // x will be initialized before y, this means that its value here is undefined
    {}          // No base class constructor in list, this is the same as calling Base()
 
    Class()
    try
      : Base ( 789 ),
        x ( 0 ),
        y ( 0 )
    {
        // no exception
    }
    catch (...)
    {
        // exception occurred on initialization
    }
};

References

  • C++11 standard (ISO/IEC 14882:2011):
  • 12.6.2 Initializing bases and members [class.base.init]
  • C++98 standard (ISO/IEC 14882:1998):
  • 12.6.2 Initializing bases and members [class.base.init]