默认构造函数是否初始化内置类型?

问题描述 投票:166回答:7

默认构造函数(由编译器创建)是否初始化内置类型?

c++ constructor initialization default-constructor built-in-types
7个回答
164
投票

隐式定义(由编译器定义)的类的默认构造函数不会初始化内置类型的成员。

但是,请记住,在某些情况下,可以通过其他方式对类的实例进行初始化。不是默认的构造函数,也不是构造函数。

例如,人们普遍认为,对于类C而言,语法C()始终会调用默认构造函数。但是实际上,语法C()执行类实例的所谓的[[value-initialization。如果它是user-declared,它将仅调用默认构造函数。 (在C ++ 03中。在C ++ 98中-仅当类为非POD时)。如果该类没有用户声明的构造函数,则C()将不会调用编译器提供的默认构造函数,而是将执行一种完全不涉及C构造函数的特殊初始化。相反,它将直接对类的每个成员进行值初始化。对于内置类型,它导致零初始化。

例如,如果您的类没有用户声明的构造函数

class C { int x; };

然后,编译器将隐式提供一个。编译器提供的构造函数将不执行任何操作,这意味着它不会初始化C::x

C c; // Compiler-provided default constructor is used // Here `c.x` contains garbage

尽管如此,以下初始化

零初始化x,因为它们使用了显式的()初始化器C c = C(); // Does not use default constructor for `C()` part // Uses value-initialization feature instead assert(c.x == 0); C *pc = new C(); // Does not use default constructor for `C()` part // Uses value-initialization feature instead assert(pc->x == 0);
()初始化程序的行为在C ++ 98和C ++ 03之间在某些方面有所不同,但在这种情况下没有区别。对于上述类C,它将是相同的:()初始化程序对C::x进行零初始化。

当然,不涉及构造函数而执行的初始化的另一个示例是聚合初始化

C c = {}; // Does not use any `C` constructors at all. Same as C c{}; in C++11. assert(c.x == 0); C d{}; // C++11 style aggregate initialization. assert(d.x == 0);


19
投票
出于所有实际目的-否


但是对于在技术上符合C ++标准的实现,答案是,它取决于对象是否为POD以及如何初始化它。根据C ++标准:

MyNonPodClass instance1;//built in members will not be initialized MyPodClass instance2;//built in members will be not be initialized MyPodClass* instance3 = new MyPodClass;//built in members will not be initialized MyPodClass* instance3 = new MyPodClass() ;//built in members will be zero initialized

但是,在现实世界中,这没有得到很好的支持,因此请不要使用它。


标准的相关部分是8.5.5和8.5.7节

18
投票
我不确定您的意思,但是:

struct A { int x; }; int a; // a is initialized to 0 A b; // b.x is initialized to 0 int main() { int c; // c is not initialized int d = int(); // d is initialized to 0 A e; // e.x is not initialized A f = A(); // f.x is initialized to 0 }

在每种情况下,我说“未初始化”-您可能会发现编译器为其提供了一个一致的值,但标准不需要它。

包括我在内,很多人都在谈论内置类型如何“有效”地具有默认构造函数。实际上,默认初始化和值初始化是标准中定义的术语,我个人必须每次都进行查询。标准中仅将类定义为具有隐式默认构造函数。


2
投票
按照标准,除非您在初始化列表中明确初始化,否则不会这样

1
投票
如先前的发言者所述-不,它们尚未初始化。

这实际上是真正奇怪的错误的来源,因为现代OS倾向于用零填充新分配的内存区域。如果您期望如此,它可能会在第一次使用。但是,随着您的应用程序不断运行,delete -ing和new -ing对象,您迟早会遇到以下情况:您期望零,但存在来自较早对象的非零残差。

所以,为什么这不是新分配的所有new版本的数据?是的,但并非总是来自操作系统。操作系统倾向于使用更大的内存块(例如一次4MB),因此所有微小的单字(这里为三个字节)的分配和释放都在uyserspace中处理,因此不会被清零。

PS。我写了“倾向于”,即您第一次都不能依靠成功...


-5
投票
从技术上讲,它确实通过使用它们的默认构造函数对它们进行了初始化,但附带的是,除了为它们分配内存外,什么也不做。

如果您想知道的是int是否将它们设置为合理的值,例如0,则答案为“否”。


-8
投票
没有默认构造函数分配内存并调用任何父级的无参数构造函数。
© www.soinside.com 2019 - 2024. All rights reserved.