这些初始化之间有什么区别?

What is the difference between these initializations?

本文关键字:什么 区别 之间 初始化      更新时间:2023-10-16

我曾经知道未初始化的成员变量是用垃圾值初始化的。

但是,如果类中存在未初始化的指针变量,则所有未初始化的成员变量都将初始化为零。

我认为指针变量只是指向堆内存中的一个实例。

为什么其他变量会发生变化?

我不知道这些初始化之间有什么区别。

以下是我逐步尝试的代码。

#include <iostream>
using namespace std;
class Test {
private:
int val1;
int val2;
public:
void PrintValue() {
cout << "val1: " << val1 << endl;
cout << "val2: " << val1 << endl;
}
};
int main() {
Test a;
a.PrintValue();
}

然后,结果是

val1: -858993460
val2: -858993460

在此代码中,我添加了"int* ptr = new int">,如下所示。

#include <iostream>
using namespace std;
class Test {
private:
int val1;
int val2;
int* ptr = new int;
public:
void PrintValue() {
cout << "val1: " << val1 << endl;
cout << "val2: " << val1 << endl;
}
};
int main() {
Test a;
a.PrintValue();
}

结果是这样的。

val1: 0
val2: 0

为什么会这样?

我正在使用VS社区2019并构建工具v142。

没有任何变化。作为默认初始化的效果,数据成员val1val2将被初始化为不确定值;任何使用它们都会导致 UB,一切皆有可能。

否则,不执行任何操作:具有自动存储持续时间的对象(及其子对象(初始化为不确定值。

具有自动和动态存储持续时间的非类变量的默认初始化将生成具有不确定值的对象

这里的区别在于,添加int* ptr = new int会将底层类从POD(纯旧数据(类更改为non-POD类。
如果您尝试使用第一个示例

class Test {
public:
int val1;
int val2;
void PrintValue() {
cout << "val1: " << val1 << endl;
cout << "val2: " << val1 << endl;
}
};
int main() {
Test t;
cout << t.val1 << endl;
}

然后你会得到一个编译器错误,因为它知道你正在尝试访问未初始化的变量。

但是,当您添加更复杂的int* ptr = new int时,您的类将变为非 POD,因此编译器会为您创建一个默认构造函数,该构造函数将为您初始化变量。
因此

class Test {
public:
int val1;
int val2;
int* ptr = new int;
void PrintValue() {
cout << "val1: " << val1 << endl;
cout << "val2: " << val1 << endl;
}
};
int main() {
Test t;
cout << t.val1 << endl;
}

这变得合法,现在将编译 (尽管正如其他答案指出的那样,虽然它的输出可能看起来更干净,并且不会抛出错误,但访问这些默认的初始化变量可能仍然是 UB(

有关 POD 的更多信息