C ++用户定义的空默认构造函数与隐式或默认的默认构造函数
Posted
技术标签:
【中文标题】C ++用户定义的空默认构造函数与隐式或默认的默认构造函数【英文标题】:C++ User defined empty default constructor vs implicit or default-ed default constructor 【发布时间】:2017-03-10 04:25:28 【问题描述】:我正在使用 Visual Studio 2013。
我有以下代码
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;
我认为用户定义的默认构造函数和隐式定义的默认构造函数是等价的,但在我看来它们不是。
编译器定义的默认构造函数究竟是如何工作的?
在这种情况下,我对使用编译器定义的默认构造函数持谨慎态度,并始终提供我自己的,即使有时是空的默认构造函数。我是不是误会了什么?
【问题讨论】:
【参考方案1】:在实现时,implicitly-defined default constructor 做与用户定义的构造函数相同,但具有空主体和空初始化列表。
如果隐式声明的默认构造函数没有定义为delete,如果odr-used是由编译器定义的(即生成并编译一个函数体),和用户的效果完全一样——定义了具有空主体和空初始化列表的构造函数。
和
Foo foo1; // No Warning. fPtr is initialized to NULL, f is set to 0.0.
没有。不仅对于第二个代码示例,即使对于第一个代码示例,foo1.fPtr
和 foo1.f
也没有初始化;空的用户定义构造函数根本不初始化任何成员。
关于编译器警告,似乎 MSVS 认为如果提供并调用了用户定义的构造函数,则可以假定该对象已被初始化。但是你需要确保构造函数做或不做你所期望的。
请注意,它们仍然有一些微妙的不同副作用;比如list initialization和value intialization,(但这里没有使用default initialization)。例如对于
Foo foo1;
那么对于第一种情况,将调用用户定义的默认构造函数;因为它什么都不做 foo1.fPtr
和 foo1.f
仍将未初始化;但是对于第二种情况,将执行aggregate initialization(因为缺少用户定义的构造函数),然后将foo1.fPtr
和foo1.f
进行值初始化。即foo1.fPtr
初始化为nullptr
,foo1.f
初始化为0
。
【讨论】:
我不太明白您所说的“不。即使对于第一个代码示例,foo1.fPtr 和 foo1.f 也没有初始化;用户定义的构造函数实际上什么都不做。”。事实是,在第一种情况下,用户定义的构造函数被Foo foo1;
和 Foo foo1
调用,并且成员被正确地初始化为其默认值,即 NULL 和 0.0,所以我假设用户定义的构造函数确实做了一些事情。
@Hrachya_h 不,它们没有被初始化,例如rextester.com/JVFH58493。
Foo foo1;
在两个示例中都没有初始化成员,因为没有任何初始化。如果它们被初始化为零,则它是编译器的随机未定义行为。在这些示例中无法保证。
“隐式定义的默认构造函数与用户定义的具有空主体和空初始化列表的构造函数执行相同的操作。”最近有变化吗?因为不习惯。使用隐式定义的构造函数进行值初始化将使成员初始化为零,并且在用户定义的构造函数为空等的情况下什么也不做。您似乎在最后一段中说了这么多。
@juanchopanza 我的意思是实现,隐式定义的默认构造函数与空的用户定义构造函数做同样的事情。是的,它们对值初始化和列表初始化(聚合初始化)有不同的副作用。以上是关于C ++用户定义的空默认构造函数与隐式或默认的默认构造函数的主要内容,如果未能解决你的问题,请参考以下文章