4

我正在学习 C++,我对 int 变量的初始化有点困惑。

此代码(包括注释)是 Nawaz 在本主题中的回答的复制/粘贴为什么 C++ 需要用户提供的默认构造函数来默认构造 const 对象?

struct POD
{
  int i;
};

POD p1; //uninitialized - but don't worry we can assign some value later on!
p1.i = 10; //assign some value later on!

POD p2 = POD(); //initialized

对于 p2,我了解正在发生以下情况:

  • 调用默认构造函数 POD() 来创建临时 POD 对象。构造函数不是用户定义的,所以它是隐式的。对于像 int 这样的内置类型,隐式默认构造函数什么都不做(不初始化)。因此包含一些随机的东西。
  • 调用复制构造函数以使用临时 POD 对象(其i仍未初始化)创建 p2。因此 p2 的 i 成员也不应该被初始化。

但是,评论说 p2 已初始化!欢迎任何解释。谢谢。

4

2 回答 2

9

对于像 int 这样的内置类型,隐式默认构造函数什么都不做(不初始化)。

这是真的,但也不是。默认初始化会产生一个未初始化的对象,而值初始化则不会。

为什么这些案例不同?

1. C++11, 8.5/11

如果没有为对象指定初始化器,则该对象是默认初始化的;如果不执行初始化,则具有自动或动态存储持续时间的对象具有不确定值

如果你使用int i;它会导致一个未初始化的整数!

2. C++11、8.5/10

初始化器是一组空括号的对象,即 (),应进行值初始化

如果你使用int i = int();你有一个 value-initialized i。现在,什么是值初始化?

3. C++11、8.5/7

对T 类型的对象进行值初始化意味着

  • [...](其中 T 可能是类或数组类型的一些选项)
  • 否则,对象被零初始化。

好的,现在我们知道这int i = int();意味着拥有i=0.

由于您的结构是 POD,因此对其进行值初始化意味着对其所有成员进行值初始化。

您可以使用一般行为的快捷方式

int i1, i2 = int();
std::cout << i1 << std::endl;
std::cout << i2 << std::endl;

如果 i1 所在的内存不为零,那么你可以得到输出可能是

一些价值
0

[正如@jogojapan 正确提到的那样:i1首先阅读是未定义的,所以不要这样做。您很可能会观察到我在此处描述的内容,但由于标准不强制编译器以这种方式运行,因此i1可能为零,或者以任何其他奇怪的方式破坏预期结果。]

请注意以下事项:

注意:由于初始化程序的语法不允许 (),

X a();

不是类 X 的值初始化对象的声明,而是一个不带参数并返回 X 的函数的声明。

强调标准报价是我的。

于 2013-07-17T03:06:41.720 回答
3

如果类类型POD没有用户定义的构造函数(如您的示例中的情况),POD() 则不调用默认构造函数。相反,对象的创建根本不使用任何构造函数。编译器执行临时对象的所谓值初始化。值初始化是一种自给自足的初始化方法,它不一定使用构造函数。相反,整个对象的值初始化递归地执行其所有子对象的值初始化,一个接一个。对于类型的成员,int值初始化意味着零初始化。

这就是为什么POD().i保证为零。任何构造函数都没有将那个零放在那里。该零是通过值初始化放置在那里的。

于 2013-07-17T02:57:53.157 回答