【问题标题】:Is a float member guaranteed to be zero initialized with {} syntax?浮点成员是否保证使用 {} 语法初始化为零?
【发布时间】:2021-12-05 07:52:34
【问题描述】:

在 C++17 中,考虑S 是具有已删除默认构造函数和浮点成员的结构的情况,当 S 用空大括号初始化时,标准保证的浮点成员为零初始化?

struct A {
  int x{};
};

struct S
{
  S() = delete;
 
  A a;
  float b;
};

int main()
{
  auto s = S{}; // Is s.b guaranteed to be zero?
}

在我看来,cppreference.com 并不清楚,两者都说:

如果初始化子句的数量小于成员的数量并且 basesor 初始化列表完全为空,则剩余的成员和基 (C++17 起)由它们的默认成员初始化器初始化,如果在类定义中提供, 否则 (C++14 起) 根据通常的列表初始化规则从空列表复制初始化聚合体)。如果引用类型的成员是这些剩余成员之一,则程序是非良构的。

(from here),这意味着b保证为零

在所有情况下,如果使用空的大括号 {} 对并且 T 是聚合类型,则执行聚合初始化而不是值初始化。

(from here)

这意味着 b 不能保证为零。

还有一个讨论似乎暗示虽然不能保证,但所有已知的编译器无论如何都会进行零初始化:

标准规定当类具有用户提供或删除的默认构造函数时不执行零初始化,即使重载决议未选择该默认构造函数。如果选择了未删除的默认默认构造函数,所有已知的编译器都会执行额外的零初始化。

与Why does aggregate initialization not work anymore since C++20 if a constructor is explicitly defaulted or deleted?相关

【问题讨论】:

  • C++20 修正了这个愚蠢的规则
  • @StoryTeller-UnslanderMonica 你有关于 C++20 修复的链接吗?
  • 这是投进 C++20 的论文wg21.link/P1008R1
  • @StoryTeller-UnslanderMonica 感谢您的链接。我发现了explicit 技巧并感谢您回答自己。从技术上讲,我仍在寻找关于 b 是否会被零初始化的答案,但实际上显式技巧解决了我的真正问题!
  • 乐于助人。我觉得我应该指出,这个晦涩的怪癖确实有一个好处。它允许您编写不允许不确定值的聚合。考虑wandbox.org/permlink/aq1t3bMV9ORogvMy - 并注意仅禁用默认(和有问题的)初始化。我仍然同意这条规则太神秘太奇怪了,不能留下来,但这并不全是坏事。

标签: c++ c++17 language-lawyer


【解决方案1】:

这是 fixed in C++20 的 C++ 怪癖。同时,您可以将explicit 添加到已删除的默认构造函数中,以强制结构变为非聚合,并使您的代码有保证的编译错误:

struct A {
  int x{};
};

struct S
{
  explicit S() = delete;
 
  const A a;
  const float b;
};

int main()
{
  auto s = S{}; // error: call to deleted constructor of 'S'
}

【讨论】:

    【解决方案2】:

    因为S 是一个聚合,S{} 将执行聚合初始化。标准中关于当列表中没有初始化器时如何初始化成员的规则是basically what you cited:

    • 如果元素具有默认成员初始化程序 ([class.mem]),则从该初始化程序初始化元素。
    • 否则,如果元素不是引用,则从空的初始化列表 ([dcl.init.list]) 复制初始化元素。

    所以对于 b,这相当于 float b = {};。根据列表初始化的规则,我们必须得到all the way down to 3.10:

    否则,如果初始化列表没有元素,则对象被值初始化。

    并且值初始化会将float初始化为0。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-05
      • 1970-01-01
      • 2021-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-01
      相关资源
      最近更新 更多