【问题标题】:C++ zero initialization without constructor没有构造函数的 C++ 零初始化
【发布时间】:2021-04-29 08:15:04
【问题描述】:

我不明白对于具有其成员默认值的结构的零初始化会发生什么。

如果我有这些结构:

struct A {
  int *a;
  int b;
};

struct B {
  int *a;
  int b;
  B() : b(3) {}
};

struct C {
  int *a;
  int b = 3;
};

我们可以毫无疑问地说:

  • A a; 未初始化所有字段
  • A a{}; 是 {nullptr, 0}
  • B b;B b{}; 都是 {garbage, 3} (构造函数被调用)

现在不清楚当我执行以下操作时会发生什么,以下是使用 gcc 的结果:

C c; // {garbage, 3}
C c{}; // {nullptr, 3}

问题是:C c{}; 保证 C::a 被初始化为nullptr,换句话说,如果像C 这样的默认成员仍然为零初始化其他成员,如果我明确地构造了像C c{};这样的对象?

因为如果我有一个与C 执行相同操作的构造函数(例如在B 中),则不会发生这种情况,因此其他成员 零初始化,但为什么呢? BC有什么区别?

【问题讨论】:

  • ot:我想我是迂腐的,但“垃圾”一词在这里完全用词不当。没有垃圾。它是一个不确定的值。如果不违反语言规则(未定义的行为),您将无法看到该值,如果您这样做,它可能会显示为垃圾,但它不是。
  • 之所以提到它,是因为“垃圾神话”有时很难讨论此类实验的结果:事实上,您无法区分 3nullptr 和“垃圾”,因为如果您的代码具有未定义的行为,无法保证您得到错误/意外的输出
  • 答案在 C++11 和 C++14 之间发生了变化。在 C++11 中,C 不是聚合,并且列表初始化调用了一个隐式定义的构造函数,该构造函数不会初始化 a。在 C++14 中,C 是一个聚合,并且列表初始化将所有未在 brace-init 列表中或由成员声明中指定的初始化程序赋予值的成员初始化为零.由于用户定义的构造函数,B 不是聚合方式。
  • 相关文章:the fickle aggregate.

标签: c++ struct constructor initialization


【解决方案1】:

从 C++14 开始,C 是一个聚合(如 A),C c{} 语法执行聚合初始化。这部分包括:

[dcl.init.aggr]/8 如果列表中的 initializer-clauses 少于非联合聚合中的元素,则每个元素未显式初始化的初始化如下:
(8.1) — 如果元素具有默认成员初始化程序 (12.2),则从该初始化程序初始化元素。
(8.2) — 否则,如果元素不是引用,则从空的初始化列表 (11.6.4) 复制初始化元素。
(8.3) — 否则,程序格式错误。

所以C c{}; 等价于C c{{}, 3};。用空列表初始化 int* 成员会导致它被零初始化。

在 C++11 中,C 不是聚合(具有默认成员初始值设定项是不合格的),C c{}; 调用隐式定义的构造函数,使 c.a 成员未初始化。

在标准的所有版本中,B 不是一个聚合,因为用户定义的构造函数。 B b{}; 调用该构造函数,该构造函数显式初始化 b 成员并选择不初始化 a

【讨论】:

    【解决方案2】:

    Aggregate initialization - cppreference.com

    • 如果初始化子句的数量小于成员数或初始化列表完全为空,则剩余成员为value-initialized。如果引用类型的成员是这些剩余成员之一,则程序是非良构的。

    (直到 C++11)

    • 如果初始化子句的数量小于成员和基数(C++17 起)或初始化器列表完全为空,剩余的成员和基数(C++17 起)将由它们的@987654323 初始化@,如果在类定义中提供,否则 (C++14 起) 根据通常的 list-initialization 规则从空列表复制初始化(对非类类型和非聚合类执行值初始化)使用默认构造函数,以及聚合的聚合初始化)。如果引用类型的成员是这些剩余成员之一,则程序是非良构的。

    (C++11 起)

    所以A a{};所有成员都默认初始化

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-29
      • 1970-01-01
      • 2018-06-30
      • 2016-11-28
      • 2015-07-13
      • 1970-01-01
      • 2021-12-16
      • 1970-01-01
      相关资源
      最近更新 更多