【问题标题】:Why zero-initialize when it's not necessary为什么在不需要时进行零初始化
【发布时间】:2020-09-01 20:20:53
【问题描述】:

我开始使用 C++ 并看到课程/教程的作者对变量进行零初始化,并开始想知道为什么零初始化甚至是一个选项?您可以只识别变量并稍后分配一个值。有性能优势吗?或者这样读者可以更好地理解代码?

C++ 示例:

选择1:

#include <iostream>

int main()
{
    int x{ }; //<-- difference here
    std::cout << "Enter a number: "; 
    std::cin >> x; 
    std::cout << "You entered: " << x << '\n';
    return 0;
}

选择2:

#include <iostream>

int main()
{
    int x; //<-- difference here
    std::cout << "Enter a number: ";
    std::cin >> x;
    std::cout << "You entered: " << x << '\n';
    return 0;
}

这两个选项您将获得相同的输出。

也许是我忘记了一些琐碎的事情(也没有在网上找到)。

【问题讨论】:

  • 在旧版本的 C++ 中,如果 std::cin 失败,它将使对象保持不变。所以在旧版本的 C++ 中,如果std::cin 失败,第二个示例实际上是未定义的行为。在较新版本的 C++ 中,第二个选项很好。
  • 任何 API 调用都需要牢记这一点。有时“out”参数只有在成功时才会改变。
  • 如果您对int 进行零初始化,在该int 将始终在被读取之前被覆盖,我希望编译能够做出该决定并删除初始化。因此,即使没有必要,显式初始化变量通常也无害。
  • @SamimMaschal 函数可以成功也可以失败。在控制台 I/O 的情况下,如果控制台在操作系统层由于某种未知原因(即内存不足等)失败,或者如果用户的输入与读取的预期不匹配,则读取操作可能会失败(即,用户在需要整数的地方输入字母等)。如果任何函数有一个指示成功/失败状态的输出值,你应该时刻注意它。
  • 如果在两个程序中都输入“z”会发生什么?你预计会发生什么?

标签: c++ initialization theory


【解决方案1】:

您的代码没有明显差异。

考虑在用户输入之前有人修改了代码以查看x 的值。那么这就完全没问题了:

int x{ }; //<-- difference here
std::cout << "x before: " << x << '\n';
std::cin >> x; 
std::cout << "You entered: " << x << '\n';
return 0;

这段代码:

int x; //<-- difference here
std::cout << "x before : " << x << '\n';
std::cin >> x; 

undefined behavior。代码格式错误,编译器不需要发出错误或警告。大多数编译器都可以很好地警告上述代码,但一般来说,这不是你可以指望的。因此,应不惜一切代价避免未定义的行为。

广泛接受的准则是始终初始化变量。换句话说,只有在可以初始化变量时才声明它。例如,请参阅 C++ CoreGuideline ES.20:Always initialize an object

并非总是可以在初始化时为变量赋予有意义的值。在您的示例中,x 就是这种情况。因为std::cin 总是会给x 赋值(这在C++11 之前是不同的)我们并不关心之前x 的值是多少。不过,按照指南,我们应该写 int x{}; 而不是 int x;

请注意,在 C++11 之前,当从流中提取失败时该值保持不变,因此此类代码

 int x;
 std::cin >> x;
 std::cout << x;

是错误和危险的。如前所述,这在 C++11 中发生了变化(现在在提取失败时将零写入x)。然而结论还是一样:你最好在声明x的时候就初始化它。

【讨论】:

  • 输入操作失败怎么办?这不是让x 保持之前的价值吗?
  • @DavidSchwartz 如果失败,0 是自 C++11 开始编写的。不要问我为什么。这是我想知道为什么它是最多的一个变化
  • @idclev463035818:你不是刚刚解释了为什么要制作它吗?为了防止该代码展示UB?由于输入错误不是(默认情况下)异常,因此将值设置为已定义的值是最合理的行为,因为错误会被忽略。
  • @NicolBolas 有点,是的。我只是不完全相信我自己的论点。我天真的猜测是,大多数以前是 UB 的代码现在仍然有一个错误,但也许从某些代码中删除 UB 已经足以证明改变
【解决方案2】:

作者在下一章解释了为什么不使用未初始化的变量是有益的。

“注意避免所有导致未定义行为的情况,例如使用未初始化的变量”。

不过,如果您知道所有内容都已定义,那应该不是问题。

来源: https://www.learncpp.com/cpp-tutorial/uninitialized-variables-and-undefined-behavior/

【讨论】:

    猜你喜欢
    • 2023-01-18
    • 2016-10-07
    • 1970-01-01
    • 2021-12-16
    • 2011-06-08
    • 2013-10-14
    • 2015-09-09
    • 2019-05-30
    • 2022-06-15
    相关资源
    最近更新 更多