【问题标题】:Bool member variable in class is set to True when uninitialized类中的 Bool 成员变量在未初始化时设置为 True
【发布时间】:2020-12-18 12:32:37
【问题描述】:

更新: 我得到真实的原因是因为任何不是 0 的东西都会被认为是真实的,这显然对我在未初始化时变得虚假的可能性有多大意义。

我在 StackOverflow 上阅读了与我的问题类似的帖子,它谈到初始化所有成员变量是一种很好的做法,我同意这一点。 发帖:Boolean variables aren't always false by default?

这篇文章有点老了(9 年前),所以我只是认为可能在新的 C++ 版本中发生了一些变化,我目前使用的是 C++17。我还有一个与帖子中讨论的问题略有不同的问题。

我知道,如果一个变量未初始化,它可能包含一些“垃圾数据”,或者正如帖子中的一个答案所说(我认为这就是他们的意思,但我不是 100% 确定),“如果没有显式初始化 -- 将包含任意值。"。

我已经尝试过测试,结果表明当我没有初始化我的变量时,它们包含随机数(对于 int,double)。我还测试了 std::string 但从我看到的默认情况下它们设置为“”。

无论如何,现在当我尝试使用内置类型 bool 时,我总是会得到 true(在构造类之后,但该布尔值再次从未初始化,我会进入调试并查看该值是否为 true) ,令我困惑的是,无论我尝试测试多少次,这是否只是真假中的一个随机值,如果有时它是假的,它总是设置为真。如果未初始化,值不应该是“随机”的吗?为什么它总是设置为 true(同样是当我的类的成员变量在构造时未初始化)。

我尝试过的解决方案: 明明一个只是初始化构造,但我想到了另一个……

如果在构造时我希望它是真的而不是假的,但是当它没有被构造为设置为假时,那么当我有一个指向我的对象的指针向量时,我可以检查我没有在阅读通过检查该布尔值是否设置为 true(如果已初始化)或 false 来跟踪指针时未初始化的对象。我将无法使用将构造初始化为 false 的方法 1,还因为如果我们要反转行为,我不能依赖未初始化的布尔成员变量将是什么,正如我在上面的段落中提到的那样不确定由于我得到的结果而导致的行为。我做了以下,它的工作...

class Testing{
private:
    bool condition{false} // Initalize it here which kind of makes me confused but it works

public:
    Testing() : condition{true} {} // Constructor setting the condition value to true

};

有人可以解释这样做是否错误,就我个人而言,我从未见过有人这样做,但我尝试过并且没有给出错误。

【问题讨论】:

  • 具体实现 - false 通常为 0,而 true 为任何其他值。所以你会期待更真实的结果。然而程序有未定义的行为(读取一个未初始化的值)所以任何关于它的行为的分析和推理都是没有意义的。
  • 你看到的更真实,因为任何非零值都被转换为 true
  • 未初始化的变量是未初始化的,没有初始值。有可能某些架构会将内存标记为未初始化,并且尝试从中读取会导致程序出错并终止——这是一种可能性(许多)未定义的行为。初始化 bool 的代码将具有已知的初始值,这通常是 Good Thing™。
  • 未初始化的值不是随机的。这是任意的。而且我很迂腐。在调试器中运行程序,查看 bool 的数值是否始终为常数,或者是否每次都是不同的非零数。
  • 我也测试了 std::string 但从我看到的默认情况下它们设置为 ""。 -- 这是因为std::string 的默认构造函数设置了字符串为空。不可能有未初始化的std::string

标签: c++


【解决方案1】:

虽然bool 在概念上只包含一位信息,但 C++ 标准的要求意味着bool 对象必须占用至少八位。编译器可以通过三种主要方式在位级别上表示 bool

  1. 所有位都归零为假;所有位都为真(0x00 与 0xFF)
  2. 所有位都归零为假;最低位为真(0x00 与 0x01)
  3. 所有位都归零为假;至少有一点是真的(0x00 与其他任何东西)

(请注意,这种表示方式的选择在程序的效果中通常不可见。无论位如何表示,bool 在转换为更宽时会变为 0 或 1整数类型。只与生成的机器码有关。)

在实践中,现代 x86/x64 编译器使用选项 2。有一些指令可以让这变得简单,它使得将 bool 转换为 int 变得简单,并且比较 bools 无需额外努力。

一个副作用是,如果构成 bool 的位最终设置为 0x37,则可能会发生奇怪的事情,因为可执行代码不会这样。例如,可以采用 if 语句的两个分支。一个好的调试器在看到带有意外位模式的bool 时应该大声对您大喊大叫,但实际上它们倾向于将值显示为true

所有这些选项的共同主题是大多数随机位模式不是false 的位模式。因此,如果分配器确实将其设置为“随机”值,那么它几乎肯定会在调试器中显示为 true

【讨论】:

  • 请记住,array 有其特殊的实现来减少内存占用,实际上每个 bool 只使用一位,这在某些特殊情况下会产生一些有趣的问题...
  • @U.W.我认为您正在考虑vector<bool>,它确实专门处理了这个问题。但是vector<bool> 的元素永远不会未初始化。
猜你喜欢
  • 2011-05-19
  • 1970-01-01
  • 1970-01-01
  • 2021-06-21
  • 1970-01-01
  • 1970-01-01
  • 2013-01-07
  • 2019-03-19
相关资源
最近更新 更多