189

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

4

7 回答 7

192

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

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

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

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

class C { 
public:
  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);
于 2010-03-10T15:41:32.180 回答
23

我不太确定你的意思,但是:

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
}

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

很多人都在挥手,包括我在内,关于“有效”的内置类型如何具有默认构造函数。实际上默认初始化和值初始化是标准中定义的术语,我个人每次都必须查找。只有类在标准中定义为具有隐式默认构造函数。

于 2010-03-10T15:29:58.017 回答
20

出于所有实际目的 - 不。


然而,对于在技术上符合 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 节

于 2010-03-10T13:40:09.853 回答
3

根据标准,除非您在初始化程序列表中显式初始化

于 2010-03-10T13:10:02.563 回答
1

正如前面的发言者所说 - 不,它们没有被初始化。

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

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

PS。我写了“tend to”,即你甚至不能依赖第一次成功...

于 2010-03-10T13:37:47.107 回答
-5

从技术上讲,它确实初始化了它们——通过使用它们的默认构造函数,顺便说一句,它只是为它们分配内存。

如果您想知道它们是否被设置为ints 的 0 之类的正常值,那么答案是“否”。

于 2010-03-10T13:24:16.217 回答
-8

不。默认构造函数分配内存并调用任何父级的无参数构造函数。

于 2010-03-10T13:11:14.097 回答