我读了一本书。Lippman“内部C ++对象模型”,是否有这样的代码

class Foo { public: int val; Foo *pnext; };
void foo_bar()
{
// Oops: program needs bar's members zeroed out
Foo bar;
Foo* baz = new Foo(); // this line i added myself
if ( bar.val || bar.pnext )
// ... do something
// ...
}

它说:“对于此代码片段,未合成默认的构造函数。

确保全局对象在程序启动时具有其关联的内存“归零”。在程序堆栈中分配的本地对象和分配在自由商店中的堆对象没有将其关联的内存归零;相反,内存保留了其先前使用的任意位模式。”

在此代码中,baz对象是在堆上创建的,根据上面的说法,该对象不是全局的,也不会称为默认构造函数。我理解正确吗?

有帮助吗?

解决方案

括号进来 new Foo() 指定 价值初始化;这基本上意味着每个成员都是零启示的。相反,你说 new Foo, ,然后将成员不限化,因为它们是用于您的自动变量的。

不幸的是,要自动变量,您不能写 Foo bar(), ,因为该声明一个函数。你需要

Foo bar{};        // C++11
Foo bar = Foo();  // Historical C++

其他提示

当您这样做时:

Foo* baz = new Foo();

您正在动态分配 Foo 实例和 价值初始化 它。对于POD,这意味着成员对零进行了化。如果您说过这句话(假设非全球环境):

Foo* baz = new Foo;

然后 Foo 实例将是默认初始化的,这意味着由于它们是豆荚,因此不会执行其成员的初始化。

这也适用于自动存储实例:

Foo f0; // default initializaiton: members not zeroed out.
Foo f1 = Foo(); // value initialization: members zeroed out.
Foo f2{}; // C++11 value initialization: members zeroed out.
Foo f3(); // Ooops! Function declaration. Something completely different.

如果类没有默认构造函数(和其他构造函数),则编译器将为您创建一个。它必须,或者您将无法创建课堂的实例。但是,生成的默认构造函数将无需做任何事情。

是什么添加了空的括号集 new Foo() 确实是为了重视初始化分配的对象,这意味着成员被初始化为其“默认”值,该值对整数和浮点值和浮点值零,以及 nullptr 用于指针。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top