POD在默认初始化时是否会受到特殊对待?(C++14)

4
为什么以下代码输出0?在我的理解中,这是默认初始化(而不是值初始化),所以值应该是随机的。
#include <stdio.h>
#include<iostream>
#include<memory>

using namespace std;

struct A 
{

    int i;
    int j;
};


int main()
{
    A a;

    cout << " i is " << a.i << endl;

    return 0;
}

来自cppreference:

默认初始化的效果为:

如果T是非POD(C++11之前)类类型,则会考虑构造函数,并根据空参数列表进行重载解析。选择的构造函数(其中之一是默认构造函数)被调用以为新对象提供初始值;

如果T是数组类型,则对数组的每个元素进行默认初始化;

否则,什么也不做:具有自动存储期限的对象(及其子对象)将被初始化为不确定的值。


随机抽取时不能抽到0吗? - StoryTeller - Unslander Monica
2
在C++中有一个常见的误解,即如果有一个红色交通灯告诉你不要穿过街道,那么一定会有一辆车横穿你的路。事实上,红灯只是告诉你可能会有车横穿你的路,所以除非你想冒险,最好还是等绿灯。 - 463035818_is_not_a_number
发生的情况是结构体对象a被放置在内存中的某个位置,而ij的值反映了该内存中的内容。您事先不知道该内存中的内容,这导致它们的值是不确定的,而不是“随机”的(即使有时看起来可能是这样)。 - Some programmer dude
1
无法确认 http://coliru.stacked-crooked.com/view?id=600713a1041e98eb - Killzone Kid
@setia_,你期望获得一个随机值是不正确的。你甚至不能指望这段代码打印出任何东西。 - user7860670
显示剩余8条评论
2个回答

3

当你获取 a.i 的值时,其值未定义,你应该预期会得到任何值。

取决于系统、使用的标准库、编译器、编译器标志等因素,内存的某些部分(例如堆栈)可能被初始化为 0,但不能保证这一点。

对于 gcc 也是如此,在您的简单示例中,您可能总是会得到 0,但如果关闭优化 -O0 并编译以下代码,则可能会得到不同的结果:

#include <iostream>

struct A 
{
  int i;
  int j;
};


int foo() {
  A a;
  const int b = a.i;
  a.i = 123;
  return b;
}

int main() {
  const int n1 = foo();
  const int n2 = foo();
  std::cout << n1 << " " << n2 << std::endl;
  return 0;
}

然后(取决于操作系统、标准库、CPU等),您将得到以下输出:

0 123

在这两种情况下,a.i 都未初始化。对于第一次调用, a.i 保持一些“随机”的数字,而对于第二次调用,a 可能会被创建在相同的位置,并且此时内存的这部分仍然可能保存 123。原因是 A 被创建在堆栈上,后续对 foo 的调用很可能导致 a 被定位在相同的内存地址上。


0

根据讨论和实验,这是未定义的行为。POD在默认初始化时没有特殊处理。

clang、MSVC总是给出随机值,但gcc总是给出0。毕竟,未定义就是未定义。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接