Почему конструктор необходим в структуре const?
У меня есть код, похожий на этот:
class AClass {
public:
struct AStruct { };
AClass(){}
private:
const AStruct m_struct;
};
int main() {
AClass a;
}
Он выдает эту ошибку компиляции (с Clang LLVM версия 5.1):
error: constructor for 'AClass' must explicitly initialize
the const member 'm_struct'
Если я укажу конструктор по умолчанию для С++ 11 для struct AStruct
, я получаю ту же ошибку:
struct AStruct {
AStruct() = default;
};
Однако это решается путем написания конструктора с пустым телом:
struct AStruct {
AStruct(){} // fixed
};
Почему мне нужно указывать пустой конструктор? Разве это не автоматически создается с открытым доступом для структур?
Почему конструктор по умолчанию С++ 11 не решает проблему?
Ответы
Ответ 1
Из §8.5 [dcl.init]/7:
Если программа запрашивает инициализацию по умолчанию объекта типа const, T, T должен быть типом класса с предоставленным пользователем конструктором по умолчанию.
Конструктор по умолчанию AClass
по умолчанию инициализирует член const
(см. ниже), так что член должен иметь предоставленный пользователем конструктор по умолчанию. Использование = default
не приводит к предоставленному пользователем конструктору по умолчанию, как показано в §8.4.2 [dcl.fct.def.default]/4:
Функция предоставляется пользователем, если она объявлена пользователем и явно не установлена по умолчанию или удалено в его первом объявлении.
Элемент инициализируется по умолчанию для §12.6.2 [class.base.init]/8:
В конструкторе без делегирования, если данный нестатический элемент данных или базовый класс не обозначен идентификатором mem-initializer (включая случай, когда нет списка mem-initializer, поскольку конструктор не имеет ctor -initializer), и сущность не является виртуальным базовым классом абстрактного класса (10.4), то
- если объект является нестатическим элементом данных, у которого есть инициализатор с привязкой или равенством, объект инициализируется, как указано в 8.5;
- в противном случае, если объект является анонимным объединением или вариантом (9.5), инициализация не выполняется; - , в противном случае объект инициализируется по умолчанию (8.5).
Ответ 2
Украденный из @chris ответ, у нас есть этот параграф: §8.5 [dcl.init]/7:
Если программа запрашивает инициализацию по умолчанию объекта типа const, T, T должен быть типом класса с предоставленным пользователем конструктором по умолчанию.
Затем мы можем построить совершенно смешной случай, иллюстрирующий это ограничение:
struct Foo {};
int main() {
const Foo f;
}
который не компилируется в clang, как это диктует стандарт. Ваш код просто это, но как переменная-член другого класса/структуры.
Мы можем даже это сделать:
struct Foo {int x = 3;};
int main() {
const Foo f;
}
где все данные, очевидно, инициализированы. Этот последний пример убеждает меня, что это дефект в стандарте.
Мысль, вероятно, была связана с неинициализацией типов POD и const
, но формулировка блокирует код, который не связан. Конструкторы по умолчанию в современных С++ часто более чем достаточно хороши, а форсирование Foo(){}
- это плохая форма.