C 用户定义的空默认构造函数与隐式或默认为默认的默认构造函数

C++ User defined empty default constructor vs implicit or default-ed default constructor

本文关键字:默认 构造函数 用户 定义      更新时间:2023-10-16

我正在使用Visual Studio2013。

我有以下代码

class Foo{
public:
     Foo(){};
     Foo* fPtr;
     float f;
};
int main()
{
    Foo foo1; // No Warning. fPtr is initialized to NULL, f is set to 0.0.
    Foo foo2(foo1); // Compiles fine. Uses compiler generated copy constructor
    return 0;
}

现在考虑相同的代码,但没有用户定义的默认构造函数。

class Foo{
public:
               // No user defined default constructor, or equivalently
               // Foo() = default;
     Foo* fPtr;
     float f;
};
int main()
{
    Foo foo1; // Neither fPtr nor f are initialized, both contain garbage.
   //Foo foo2(foo1); // error C4700: uninitialized local variable 'foo1' used
    return 0;
}

我认为用户定义的默认构造函数和隐式定义的默认构造函数是等效的,但在我看来它们不是。

编译器确切定义默认构造函数如何工作?

在这种情况下,我谨慎使用编译器定义的默认构造函数,并始终提供自己的默认构造函数,即使有时也可以提供自己的默认构造函数。我是在误解某些东西吗?

在实现时,隐式定义的默认构造函数 die 与带有空白的用户定义的构造函数相同的东西。

如果未定义为删除的隐式默认构造函数,则如果使用ODR使用,则将其定义(即,将函数正文生成和编译),并且与用户的效果完全相同定义的构造函数,带有空体和空初始化器列表。

Foo foo1; // No Warning. fPtr is initialized to NULL, f is set to 0.0.

否。不仅对于第二代码示例,即使对于第一代码样本,foo1.fPtrfoo1.f也没有初始化;空用户定义的构造函数根本不初始化任何成员。

以及关于编译器的警告,MSV似乎认为如果提供并调用了用户定义的构造函数,则可以认为该对象已被初始化。但是您需要确保构造函数做或不做您预期的事情。

请注意,它们仍然具有一些微妙的副作用。例如列表初始化和价值Intialization(但不是此处使用的默认初始化)。例如

Foo foo1{};

然后,对于第一种情况,将调用用户定义的默认构造函数;因为它没有任何作用foo1.fPtr,并且foo1.f仍然非专业化;但是对于第二种情况,将执行汇总初始化(由于用户定义的构造函数缺少),那么foo1.fPtrfoo1.f将进行价值initialized。即foo1.fPtr初始化为nullptrfoo1.f初始化为0