C++中使用{}对union聚合初始化的编译器行为差异问题
联合体空聚合初始化编译器差异问题解析
问题代码
#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; }
结论
该差异并非未定义行为,而是GCC的实现不符合C++17及之后正式标准的规定,属于实现缺陷,Clang输出1是符合标准要求的行为。
规则解释
- 首先
U属于C++17及之后标准定义的聚合类,满足聚合类的所有判定条件:无用户提供的构造函数、无私有/保护非静态成员、无虚函数、无虚基类。 - 按照C++标准[dcl.init.aggr]章节的规定:当使用空初始化列表
{}对联合体执行聚合初始化时,将激活并初始化联合体的第一个非静态数据成员,其余成员处于未激活状态。
按照该规则,U u{}会激活第一个成员a,调用A的默认构造逻辑,最终a.x的取值为1,和Clang的输出一致。 - GCC的行为是错误地将该场景判定为值初始化,对整个联合体的内存执行了零初始化,因此得到输出0,该实现不符合正式标准的要求。
无分歧的写法
如果要避免编译器差异,可以显式指定要激活的成员,使用指定初始化语法即可,所有编译器都会按指定逻辑处理:
// 显式激活a,输出1 U u{.a = {}}; // 显式激活b,输出0 U u{.b = {}};
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

