athos athos - 2 months ago 17
C++ Question

C++: how is construction by initialization list done?

C++ allows instantiating a class, setting the public members' value via an initialization list, as the example below shows for

b1
:

class B {
public:
int i;
std::string str;
};

B b1{ 42,"foo" };
B b2();


; however, if I provide a constructor

B(int k) { }


, it won't compile.

So, what's going on behind the hood?
Is it that when no constructor is provide, the compiler will provide one? But how could it provide one with initialization list? I thought it will just provide a "blank" constructor taking no input, as the example shows for
b2
. Or does it provide both?

Answer

But how could it provide one with initialization list?

No, it won't.

Note that for list initialization B b1{ 42,"foo" };, aggregate initialization is performed.

If T is an aggregate type, aggregate initialization is performed.

And B is an aggregate type,

An aggregate is one of the following types:

array type
class type (typically, struct or union), that has 

    no private or protected non-static data members
    no user-provided, inherited, or explicit constructors (explicitly defaulted or deleted constructors are allowed)
    no virtual, private, or protected base classes
    no virtual member functions

That's why B b1{ 42,"foo" }; works well.

And If you provide a user-defined constructor, B becomes non-aggregate type, then aggregate initialization won't work again. In this case, you can only initialize B like B b1{42}; or B b2(42);, which will call the appropriate constructor.

BTW: After providing a user-defined constructor (taking one parameter), the implicitly-declared default constructor won't be declared by the compiler again. It means B b2; or B b2{}; won't work again.

BTW2: B b2(); might be a function declaration. See Most vexing parse.