是否未明确指定未初始化的数据行为?

Jim*_*mmy 6 c++ initialization

注意:我正在使用g ++编译器(我听说这是非常好的,并且应该非常接近标准).


我有一个我能想到的最简单的课程:

class BaseClass  {
  public:
    int pub;
};
Run Code Online (Sandbox Code Playgroud)

然后我有三个同样简单的程序来创建BaseClass对象并打印出他们数据的[未初始化]值.


情况1

BaseClass B1;
cout<<"B1.pub = "<<B1.pub<<endl;
Run Code Online (Sandbox Code Playgroud)

打印出:

B1.pub = 1629556548
Run Code Online (Sandbox Code Playgroud)

哪个好.我实际上认为它会被初始化为零,因为它是POD或Plain Old Datatype或类似的东西,但我想不是吗?到现在为止还挺好.


案例2

BaseClass B1;
cout<<"B1.pub = "<<B1.pub<<endl;
BaseClass B2;
cout<<"B2.pub = "<<B2.pub<<endl;
Run Code Online (Sandbox Code Playgroud)

打印出:

B1.pub = 1629556548
B2.pub = 0
Run Code Online (Sandbox Code Playgroud)

这绝对是奇怪的.我以相同的方式创建了两个相同的对象.一个被初始化而另一个没有.


案例3

BaseClass B1;
cout<<"B1.pub = "<<B1.pub<<endl;
BaseClass B2;
cout<<"B2.pub = "<<B2.pub<<endl;
BaseClass* pB3 = new BaseClass;
cout<<"B3.pub = "<<pB3->pub<<endl;
Run Code Online (Sandbox Code Playgroud)

打印出:

B1.pub = 0
B2.pub = 0
B3.pub = 0
Run Code Online (Sandbox Code Playgroud)

这是最奇怪的.它们都被初始化为零.我所做的只是添加两行代码,它改变了以前的行为.


那么这只是"未初始化的数据导致未指明的行为"的情况,还是"引擎盖下"更合乎逻辑?

我真的想了解默认的构造函数/析构函数行为,因为我觉得完全理解继承的东西非常重要.

Die*_*Epp 12

这只是"未初始化数据导致未指明行为"的情况

是...

有时,如果您调用malloc(或new调用malloc),您将获得填充零的数据,因为它位于内核的新页面中.其他时候它将充满垃圾.如果你把一些东西放在堆栈上(即自动存储),你几乎肯定会得到垃圾 - 但它很难调试,因为在你的系统上,垃圾可能有点可预测.对于堆栈中的对象,您会发现在完全不同的源文件中更改代码可以更改您在未初始化的数据结构中看到的值.

关于POD: POD是否真的是一个红色的鲱鱼.我只解释了它,因为这个问题提到了POD,并且谈话从那里脱轨了.两个相关概念是存储持续时间和构造函数.POD对象没有构造函数,但是没有构造函数的所有东西都不是POD.(从技术上讲,POD对象没有非平凡的构造函数,也没有非平凡构造函数的成员.)

储存期限:有三种. 静态持续时间用于全局变量,自动用于局部变量,动态用于堆上的对象.(这是一种简化,并不完全正确,但如果您需要完全正确的东西,您可以自己阅读C++标准.)

具有静态存储持续时间的任何内容都会初始化为零.因此,如果你创建一个全局实例BaseClass,那么它的pub成员将为零(首先).由于您将它放在堆栈和堆上,因此该规则不适用 - 并且您不会执行任何其他操作来初始化它,因此它未初始化.它恰好包含了最后一段代码留在内存中的垃圾.

通常,堆或堆栈上的任何POD都将是未初始化的,除非您自己初始化它,并且值将是未定义的,当您重新编译或再次运行程序时可能会更改.通常,任何全局POD都将初始化为零,除非您将其初始化为其他内容.

检测未初始化的值: 尝试使用Valgrind的memcheck工具,它将帮助您找到使用未初始化值的位置 - 这些通常是错误.