Может ли тип класса с удаленным конструктором по умолчанию быть инициализирован по умолчанию? - PullRequest
0 голосов
/ 17 мая 2018

Из того, что cppref говорит о инициализации значения

, если T является типом класса без конструктора по умолчанию или с предоставленным пользователем или удаленным конструктором по умолчанию , объект инициализирован по умолчанию ;

Но так как этот тип класса удалил конструктор по умолчанию , как объект может быть инициализирован по умолчанию?

Насколько я знаю, инициализация по умолчанию типа класса требует доступа к конструктору по умолчанию.Если у нас есть:

struct A {
    A() = delete;
    int k;
};

Тогда A *a = new A; потерпит неудачу, так же как и A* a = new A();.

Но A a{}; в порядке.Но почему?Согласно cppreference

В противном случае, если список фигурных скобок пуст, а T является типом класса с конструктором по умолчанию , инициализация значенияисполнено.

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Но поскольку этот тип класса удалил конструктор по умолчанию, как объект может быть инициализирован по умолчанию?

Заявление о том, что объект инициализирован по умолчанию, само по себе не означает, чтоИнициализация по умолчанию - действительная вещь.Формулировка просто направляет нас в этот процесс, она делает процесс инициализации связным, это не значит, что он должен быть успешным.

Например:

struct A {
    A() = delete;
    A(int); // not an aggregate
};

auto a = A(); 

Инициализатор - (), так что этот объект значение инициализируется .В данном случае это означает, что он инициализирован по умолчанию , что означает, что мы найдем конструктор .

Вызов этого конструктора оказывается плохо сформированным , потому что он удален, что делает всю инициализацию некорректной.Но мы добираемся до этой точки путем инициализации по умолчанию.

0 голосов
/ 17 мая 2018

Я думаю, что стандарт просто означает «если T - это тип класса с удаленным конструктором по умолчанию, тогда переходите к инициализации по умолчанию». В конце концов он потерпит неудачу, потому что конструктор, выбранный для инициализации по умолчанию, будет удален. Он используется для различения со вторым случаем, т. Е. «Если T является типом класса с конструктором по умолчанию, который не предоставлен и не удален пользователем», для этого случая сначала выполняется нулевая инициализация, затем инициализация по умолчанию, если T имеет нетривиальный конструктор по умолчанию.

A a{} нормально, но почему?

Потому что, когда A представляет собой тип агрегата , выполняется инициализация агрегата. Обратите внимание, что явно удаленные конструкторы разрешены для агрегатного типа начиная с C ++ 11.

Во всех случаях, если используется пустая пара фигурных скобок {} и T является агрегатным типом, вместо инициализации значения выполняется инициализация агрегата.

И

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

  • тип массива
  • тип класса (обычно struct или union), который имеет
    • нет личных или защищенных нестатических элементов данных
    • нет предоставленных пользователем , inherited, or explicit (since C++17) конструкторов (explicitly defaulted or deleted constructors are allowed) (since C++11)
...