8
votes

Suppose the following:

class foo
{
public:
  foo() = default;

private:
  std::string m_str = "Hello";
};

I am not able to find any documentation on cppreference.com or the C++11 draft that explains what the default constructor will do to m_str here. My natural assumption is that the compiler is smart enough to not initialize m_str in the defaulted constructor if it has already been initialized in-class, but maybe I'm wrong.

Can anyone explain the initialization behavior here? Any guarantees or is this unspecified?

2
You mean will pick-up the initializer from the class.Deduplicator
cppreference explains it on the same page where it talks about in-class initializers: en.cppreference.com/w/cpp/language/…Cubbi

2 Answers

12
votes

This is well defined and specified in [class.ctor]/5:

[...] The implicitly-defined default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with no ctor-initializer (12.6.2) and an empty compound-statement. [...]

So the defaulted constructor performs the same action as:

foo() {}

This in turn applies the brace-or-equal initializer to each data member as appropriate (cf. [class.base.init]/8).

4
votes

The form of initialization you are using for m_str is called brace-or-equal-initializer by the standard.

In the first paragraph under Intializers, the standard states:

8.5 Intializers

1 A declarator can specify an initial value for the identifier being declared. The identifier designates a variable being initialized. The process of initialization described in the remainder of 8.5 applies also to initializations specified by other syntactic contexts, such as the initialization of function parameters with argumet expressions (5.2.2) or the initialization of return values (6.6.3).


        initializer:
            brace-or-equal-initializer
            ( expression-list )
        brace-or-equal-initializer:
            = initializer-clause
            braced-init-list

And in the section on class members...

9.2 Class members

5 A member can be initialized using a brace-or-equal-initializer.

And in the section on initializing bases and members...

12.6.2 Initializing bases and members

8 In a non-delegating constructor, if a given non-static data member or base class is not designated by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer) and the entity is not a virtual base class of an abstract class (10.4), then

— if the entity is a non-static data member that has a brace-or-equal-initializer, the entity is initializedas specified in 8.5

Coming to your class,

foo() = default;

is equivalent to:

foo(){}

When a default constructor with no member initializer list is used, the member data are default initialized. In the default initialization process, for members that have a brace-or-equal-initializer, that form is used to initialize them. In your case,

foo(){}

is equivalent to:

foo() : m_str("Hello") {}