标准和 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/