【问题标题】:Should constructor initialize all the data members of the class?构造函数应该初始化类的所有数据成员吗?
【发布时间】:2015-10-14 11:52:27
【问题描述】:

我有这样的情况:

class A {
public:
  A() : n(0) {}
private:
  int n;
  int m;
}

在构造函数中初始化m 在应用程序逻辑中根本没有意义。但是,Eclipse 警告我构造函数未初始化 m。我现在无法在其他地方运行代码。警告是:

成员 'm' 未在此构造函数中初始化

那么,C++ 是鼓励我们在构造函数中初始化所有数据成员还是只是 Eclipse 的逻辑?

【问题讨论】:

  • 我称之为正确的面向对象实践:每个变量都应该被初始化并且对象准备好使用。 “没意思”?然后将其初始化为 0、-1 或 MIN_INTEGER 不会有害。
  • 正是@duffymo。我只是好奇标准中是否有什么东西促使我这样做。
  • 使用未初始化变量的值是未定义的行为。最安全的方法是在构造点初始化每个变量。对于类成员,你的构造函数应该确保每个变量都被初始化,或者它有一个自己的默认构造函数。
  • @duffymo 我认为在 OO 中(问题中没有任何关于 OO 的内容),私有成员的设置无关紧要。由类来维护需要维护的任何不变量。
  • 标准没有明确说明。但是从未初始化的变量中读取的是UB。

标签: c++ eclipse initialization language-lawyer initializer-list


【解决方案1】:

构造函数是否应该初始化类的所有数据成员?

这将是一个很好的做法。

那么,C++ 是否鼓励我们在构造函数中初始化所有数据成员?

c++ 标准不要求它。只要您在使用之前初始化所有变量,那么您的程序在这方面是正确的。

或者这只是 Eclipse 的逻辑?

很有可能。当启用所有警告时,我测试的 g++ 和 clang 版本都不会对此发出警告。该逻辑可能基于也可能不基于high integrity c++ coding standard 12.4.2 或其他一些编码标准或样式指南。

【讨论】:

    【解决方案2】:

    C++ 不要求在构造函数中初始化属性,除非是在初始化列表中必须定义值的 const 属性。

    但是,在构造函数中初始化每个属性显然是一个好习惯。由于未初始化的变量或属性,我无法计算遇到了多少错误。

    最后,每个对象都应该永久处于一致状态,其中包括公共(可访问)属性和私有属性。优化不应成为保持对象不一致的原因。

    【讨论】:

    • “我无法计算由于未初始化的变量或属性而遇到了多少错误”——这可能是我自己的说法!
    【解决方案3】:

    完全不同意所有的答案和cmets。绝对不需要在不需要时默认初始化成员。这就是 C/C++ 从不将内置类型初始化为成员或自动变量的原因——因为这样做会影响性能。当然,创建一次对象/变量时这不是问题(这就是静态变量被默认初始化的原因),但对于在紧密循环中发生的某些事情,默认初始化可能会消耗宝贵的纳秒时间。

    在我看来,此规则的一个例外是指针(如果您的代码中碰巧有原始指针)。原始指针应该被 NULL 初始化,因为无效指针是导致未定义行为的直接方式。

    【讨论】:

    • 不错的方法和 +1 以自豪地走向当前。
    • @SergeyA,指针与其他类型有何不同?未初始化的数据是未定义的行为。这里和那里。 C++ 允许您出于效率原因取消初始化变量,这并不意味着我们必须取消初始化,否则它们会运行得更慢。初始化是一项必要的任务,必须在使用存储的值之前完成(存储意味着初始化),否则你会变得很糟糕。如果您认为整数不如指针重要,只需将其用作数组的索引,您就会得到一个覆盖指针。而且 c++ 也不检查数组边界。
    • 顺便说一句,初始化是如此重要,值得构造函数的发明来做到这一点,所以你永远不会忘记这样做。
    • @LuisColorado,你完全错了。统一化的值本身通常不是未定义的行为 - 放入其中的值是未定义的,但您可以正常使用它们。另一方面,无效的指针是 - 你不能以任何方式使用它。
    • “当不需要成员时,绝对不需要默认初始化它。” - 更不可能创建一个有时掩盖错误,有时不这样做的程序在我看来,默认情况下初始化任何成员是一个很好的理由,并且只有在这种优化能够带来相关的性能优势时才保存该初始化。
    【解决方案4】:

    为了完整起见,警告来自 C/C++ 代码分析。特别是问题是Potential Programming Problems / Class members should be properly initialized

    要更改代码分析设置(在这种情况下,我建议每个项目)编辑项目属性。您可以禁用整个警告,或仅对违反警告条件的文件禁用它。

    至于 CDT 与 GCC 或 CLang 的比较,与编译器提供的代码相比,CDT 正在进行额外的代码分析。当然这是意料之中的,因为 CDT 代码分析的职权范围比编译器的职权范围更大。

    PS,如果你愿意的话,你可以阅读这个particular checker的实现。

    【讨论】:

    • 很好,如果你先回答,我会接受..公平地说,我会支持你喜欢的另一个答案! :)
    【解决方案5】:

    正如已经说过的,您应该始终初始化指针,当然 const 对象是强制性的。

    在我看来,你不应该在没有必要的时候进行初始化,但最好偶尔检查一下所有非构造函数初始化的变量,因为它们是非常频繁且难以发现的错误的来源。

    我每隔几个月运行一次 Cppcheck。这给了我一百多个“错误”警告,例如“成员变量 'foo::bar' 未在构造函数中初始化。”但偶尔它会发现一些真正的错误,所以这是完全值得的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-26
      • 2023-03-31
      • 2017-06-23
      相关资源
      最近更新 更多