c++ - 为什么在堆中创建对象或堆栈中的临时对象时,隐式构造函数将结构中的 POD 初始化为零?

标签 c++ constructor initialization default-constructor object-initialization

标准和 C++ 书说,类类型成员的默认构造函数由隐式生成的默认构造函数调用,但内置类型未初始化。但是,在这个测试程序中,在堆中分配对象或使用临时对象时,我得到了意想不到的结果:

#include<iostream>


struct Container
{
    int n;
};

int main()
{
    Container c;
    std::cout << "[STACK] Num: " << c.n << std::endl;

    Container *pc = new Container();
    std::cout << "[HEAP]  Num: " << pc->n << std::endl;
    delete pc;

    Container tc = Container();
    std::cout << "[TEMP]  Num: " << tc.n << std::endl;

}

我得到这个输出:

[STACK] Num: -1079504552
[HEAP]  Num: 0
[TEMP]  Num: 0

这是编译器特有的行为吗?我真的不打算依赖这个,但我很想知道为什么会发生这种情况,特别是对于第三种情况。

最佳答案

这是预期的行为。有两个概念,“默认初始化”和“值初始化”。如果您不提及任何初始化程序,则该对象是“默认初始化的”,而如果您确实提及它,即使是默认构造函数的 (),该对象也是“已初始化的值”。定义构造函数时,两种情况都调用默认构造函数。但是对于内置类型,“值初始化”会将内存归零,而“默认初始化”则不会。

所以当你初始化时:

Type x;

如果提供了默认构造函数,它将调用默认构造函数,但原始类型将未初始化。但是,当您提到初始化程序时,例如

Type x = {}; // only works for struct/class without constructor
Type x = Type();
Type x{}; // C++11 only

原始类型(或结构的原始成员)将被 VALUE 初始化。

同样适用于:

struct X { int x; X(); };

如果你定义了构造函数

X::X() {}

x 成员将未初始化,但如果你定义了构造函数

X::X() : x() {}

它将被 VALUE 初始化。这也适用于 new,所以

new int;

应该给你未初始化的内存,但是

new int();

应该给你初始化为零的内存。 不幸的是语法:

Type x();

由于语法歧义而不允许

Type x = Type();

必须调用默认构造函数后跟复制构造函数,如果它们都被指定且不可内联。

C++11 引入了新语法,

Type x{};

这两种情况都可以使用。如果您仍然坚持使用旧标准,这就是 Boost.ValueInitialized 的原因,因此您可以正确初始化模板参数的实例。

可以找到更详细的讨论,例如in Boost.ValueInitialized documentation .

关于c++ - 为什么在堆中创建对象或堆栈中的临时对象时,隐式构造函数将结构中的 POD 初始化为零?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4932781/

相关文章:

c++ - 绝对整数值比较和平方值比较。是等价的吗?

c++ - 在 linux 上安装后如何使 C++ 程序读取预定义的文件

c++ - 指向用户定义结构的智能指针的成员初始化列表

java - 将数组传递到构造函数以在 JList 上使用

python - super() 和父类名有什么区别?

C++ 比较器对结构 vector 进行无效排序

c++ - 尝试在同一类中创建类 vector 时出现错误

c++ - C++中的结构构造函数?

c++ - 用特殊值初始化 C++ 中的对象数组

swift - Swift 中的自定义启动 - 有没有办法以 'not' 初始化方法中的某些属性?