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

时间:2020-05-13 07:06:07

标签: c++ initialization

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

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

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

为什么要更改其他变量?

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

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

#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 community 2019并构建工具v142。

2 个答案:

答案 0 :(得分:5)

什么都没有改变。受default initialization的影响,数据成员val1val2将被初始化为不确定值;任何使用它们都会导致UB,一切皆有可能。

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

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

答案 1 :(得分:1)

此处的区别在于,添加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)

more info on POD