#новичкам
Мы уже краем уха задевали эту тему, но сегодня поговорим основательно. Вот все причины, почему дефолтный конструктор не может неявно сгенерироваться компилятором:
1️⃣ У класса есть другие конструкторы
class ParametrizedConstructor {
int total;
public:
ParametrizedConstructor(int initial_value) : total(initial_value) { };
void accumulate (int x) { total += x; };
};
Example2 ex (100); // ok
Example2 ex1; // error: no default constructorДаже если вы сами определили copy/move конструктор руками, конструктор по-умолчанию неявно генерироваться не будет:
struct UserCopyConstructor
{
UserCopyConstructor(const UserCopyConstructor&) {}
// UserCopyConstructor::UserCopyConstructor() is implicitly defined as deleted
};
struct UserMoveConstructor
{
UserMoveConstructor(UserMoveConstructor&&) = default;
// UserMoveConstructor::UserMoveConstructor() is implicitly defined as deleted
};
2️⃣ В классе есть нестатическое поле-ссылка.
Ссылка обязательно должна быть инициализирована объектом, а это невозможно сделать, не имея объект.
struct HasReference {
int& ref; // error: reference needs to be initialized
};3️⃣ В классе есть нестатическое константное поле с тривиальным конструктором по-умолчанию. Тривиальные конструкторы по сути вообще ничего не делают, кроме как начинают лайфтайм объекта. То есть все поля заполняются мусором.
Но для константных объектов подразумевается наличие определенного постоянного значения. Мусорные значения не удовлетворяют этому требованию.
struct ConstTrivial {
const int x; // int has a trivial default constructor, so cannot default construct an object
};Тем не менее, компилятор спокойно может проглотить константный член с нетривиальным дефолтным конструктором. Считается, что такой конструктор корректно инициализирует объект:
struct ConstNonTrivial {
const std::string s; // std::string has non-trivial constructor
};
ConstNonTrivial cnt; // OK, s is just empty string4️⃣ Если какой-то член класса или базовый класс имеет недоступный (private) или удалённый (
= delete) конструктор по умолчаниюstruct NoDefault {
private:
NoDefault() {} // private constructor
};
struct Derived : NoDefault {
// Derived() is implicitly deleted
};
struct DeletedDefault {
DeletedDefault() = delete; // explicilty deleted
};
struct HasDeleted {
DeletedDefault dd;
};
HasDeleted hd; // ERROR! dd has explicilty deleted default constructorЕсли знаете еще способы, пишите в комментах.
Don't be trivial. Stay cool.
#cppcore