这些初始化之间有什么区别?
What is the difference between these initializations?
我曾经知道未初始化的成员变量是用垃圾值初始化的。
但是,如果类中存在未初始化的指针变量,则所有未初始化的成员变量都将初始化为零。
我认为指针变量只是指向堆内存中的一个实例。
为什么其他变量会发生变化?
我不知道这些初始化之间有什么区别。
以下是我逐步尝试的代码。
#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。
没有任何变化。作为默认初始化的效果,数据成员val1
和val2
将被初始化为不确定值;任何使用它们都会导致 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 的更多信息
相关文章:
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- 在 .h 文件中的类中声明静态变量和在.cpp文件中声明"global"变量有什么区别
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- Qt:remove() 和 rmdir() 有什么区别
- 这 4 个 lambda 表达式之间有什么区别?
- 将向量作为类>(值)<向量启动和向量<类>[值]有什么区别
- typedef 枚举和枚举类有什么区别?
- &C::c 和 &(C::c) 有什么区别?
- ascii 和 unicode 在处理级别有什么区别吗?
- C 中的常量限定符和 C++ 中的常量限定符有什么区别?
- "ABC" 和 "ABC" ) 在C++中有什么区别?
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 引用捕获和在 lambda 中通过引用发送参数有什么区别 (C++)
- 两种访问I2C总线的方法有什么区别?
- 两种模板示例有什么区别?
- 这两种C++语法之间有什么区别?
- lua 5.0.2 模块和 5.3.5 有什么区别?
- C++中"typedef"、"using"、"namespace"和"using namespace"有什么区别?
- std::enable_if 和 std::enable_if_t 有什么区别?