3

С ++ позволяет создание экземпляра класса, устанавливая значение общественности членов группы с помощью списка инициализации, как показывает следующий пример для b1:C++: как выполняется построение списка инициализации?

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

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

; однако, если я предоставил конструктор

B(int k) { } 

, он не компилируется.

Итак, что происходит за капотом? Является ли это, когда конструктор не предусмотрен, компилятор предоставит один? Но как он может предоставить список инициализации? Я думал, что он просто предоставит «пустой» конструктор без ввода, как показывает пример для b2. Или он обеспечивает оба?

ответ

5

Но как он может предоставить список инициализации?

Нет, не будет.

Отметьте, что для list initializationB b1{ 42,"foo" };, aggregate initialization выполнено.

Если T является совокупным типом, выполняется инициализация агрегата.

И Bявляетсяaggregate type,

Агрегат является один из следующих типов:

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 

Вот почему B b1{ 42,"foo" }; работает хорошо.

И если вы предоставляете определяемый пользователем конструктор, то B становится неагрегатным типом, тогда инициализация агрегата не будет работать снова. В этом случае вы можете только инициализировать B, например B b1{42}; или B b2(42);, который вызывается соответствующим конструктором.

BTW: После предоставления пользовательского конструктора (с одним параметром) implicitly-declared default constructor не будет объявлен компилятором еще раз. Это означает, что B b2; или B b2{}; больше не будет работать.

BTW2: B b2(); может быть объявлением функции. См. Most vexing parse.