c++默认值初始化随输入输出流而改变



我正在研究两个代码段的有趣行为,这给了我意想不到的行为。

描述行为

代码段1:
#include <iostream>
using namespace std;
int main()
{
long long n;
long long m;

// cin >> n;
cout << m;
return 0;
}

当我运行这个(例如在https://www.onlinegdb.com/online_c++_compiler中)时,在控制台中打印的值(变量m中的值)是0。这是预期的,并且对应于long long类型的默认初始化为0(零初始化)的事实。

代码段2:
#include <iostream>
using namespace std;
int main()
{
long long n;
long long m;

cin >> n;
cout << m;
return 0;
}

通过用cin取消注释行并添加任何值,我不会得到0,而是根据我输入的n的数字获得不同的值。此行为的其他特征有:

  1. 对于不同的n输入值,我们得到不同的m值。
  2. 每次n给定相同的值,m也得到相同的值。
  3. 定义nmstatic结果是预期的行为,即m携带值0。
  4. 如果m,nints,同样的行为仍然存在

意外的行为是m没有默认初始化为0。

讨论

我的解释
  1. 未注释的cin >> n行创建一个新线程执行。
  2. 新线程创建一个新的堆栈,所有的局部变量都被复制到这个堆栈中。
  3. 由于m没有在原始堆栈中初始化,因此它携带的值在新堆栈中是不确定的。它取决于当前堆栈的状态。但是堆栈的状态取决于原始复制堆栈的状态,而原始复制堆栈的状态又取决于输入n的值。

问题我的解释与特征3一致。然而,我不知道如何使用单个线程来检查这一点。此外,原因可能不仅仅是与堆栈相关的,这样即使只有一个线程,该行为也会持续存在。你觉得呢?

c++初始化是超级复杂。然而,这种情况相当简单(抛开令人困惑的术语;)。您是对的,mn都是默认初始化的。不过,紧接着你的解释就错了。它以

开头

这是预期的,并且对应于long long类型的默认初始化为0(零初始化)。

long long int的默认初始化是而不是零初始化。实际上它根本没有初始化。从cppreference:

在三种情况下执行默认初始化:

  1. 当声明具有自动、静态或线程本地存储持续时间的变量而没有初始化时;

[…]

默认初始化的效果如下:

  • 如果T是一个非pod(直到c++ 11)类类型,[…]long long不是类类型…]
  • 如果T是数组类型,[…][long long不是数组类型]
  • 否则,不进行初始化:具有自动存储持续时间的对象(及其子对象)包含不确定的值。

读取不确定的值是未定义行为。添加或删除看似不相关的代码行来改变输出是未定义行为的典型影响。代码的输出可以是任何东西。

最新更新