c++ - 在 C++ 中使用 `{}` 聚合初始化 union

标签 c++ language-lawyer unions aggregate-initialization

在下面的程序中 union U有两个字段 ab ,每个都有不同的默认值。如果创建了一个 U 类型的变量使用聚合初始化 {} union 的值(value)和活跃成员是什么?

#include <iostream>

struct A { int x = 1; };
struct B { int x = 0; };

union U {
    A a;
    B b;
};

int main() {
    U u{};
    std::cout << u.a.x;
}
令人惊讶的是,编译器在这里出现分歧:Clang 打印 1和 GCC 打印 0 , 演示:https://gcc.godbolt.org/z/8Tj4Y1Pv1
其中一个编译器是否存在错误,或者此处的行为不是由标准定义的?

最佳答案

Clang 是对的,GCC 是错的
根据 [dcl.init.aggr]/1 :

An aggregate is an array or a class ([class]) with

  • (1.1) no user-declared or inherited constructors ([class.ctor]),
  • (1.2) no private or protected direct non-static data members ([class.access]),
  • (1.3) no virtual functions ([class.virtual]), and
  • (1.4) no virtual, private, or protected base classes ([class.mi]).
A , BU都是聚合类,尽管前者是非 union 聚合类,前者不符合条件。
根据 [dcl.init.aggr]/5 [ 重点 矿]:

For a non-union aggregate, each element that is not an explicitly initialized element is initialized as follows:

  • (5.1) If the element has a default member initializer ([class.mem]), the element is initialized from that initializer.
  • (5.2) Otherwise, if the element is not a reference, the element is copy-initialized from an empty initializer list ([dcl.init.list]).
  • (5.3) Otherwise, the program is ill-formed.

If the aggregate is a union and the initializer list is empty, then

  • (5.4) if any variant member has a default member initializer, that member is initialized from its default member initializer;
  • (5.5) otherwise, the first member of the union (if any) is copy-initialized from an empty initializer list.

因此
U u{};

是聚合初始化,结果是 union 类的第一个数据成员,即数据成员a类型 A (这是一个非 union 聚合类),是从一个空的初始化列表中复制初始化的。作为单个数据成员 x类型 A有一个默认的成员初始值设定项,然后按照 [dcl.init.aggr]/5.1以上,数据成员x由其默认成员初始值设定项初始化。
因此,Clang 是正确的,而 GCC 是错误的。

GCC 错误报告
  • Bug 102013 - Incorrect aggregate initialization of union
  • 关于c++ - 在 C++ 中使用 `{}` 聚合初始化 union ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68881411/

    相关文章:

    c++ - 如果这不是 boost::lockfree::detail::freelist 中的错误,我在这里缺少什么?

    c++ - 在 Linux 中构建时出现 Mysqlcppconn8 和 cmake 错误

    c++ - std::vector 等不必要地(错误地?)实例化嵌套模板参数类型

    c++ - 标准在定义可见性方面对unordered_set的Value类型有什么要求

    c++ - 如何使用匿名结构/union 编译 C 代码?

    c++ - 无限大小的整数?

    c++ - 是否允许 C++ 编译器优化器破坏我多次调用析构函数的能力?

    c - 线程为 "suspended"对 POSIX 意味着什么?

    c - 具有在 C 中包含 union 的结构的动态数组

    c - memcpy 指向 union 的空指针