Fed*_*dor 5 c++ unions language-lawyer aggregate-initialization
在下面的程序中,联合U有两个字段a和b,每个字段都有不同的默认值。如果U使用聚合初始化创建一个类型的变量,{}则联合的值和活动成员是什么?
#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;
}
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,编译器在这里有分歧:Clang 打印1和 GCC 打印0,演示:https : //gcc.godbolt.org/z/8Tj4Y1Pv1
其中一个编译器是否存在错误,或者此处的行为不是由标准定义的?
聚合是一个数组或一个类([class])
- (1.1) 没有用户声明或继承的构造函数 ([class.ctor]),
- (1.2) 没有私有或受保护的直接非静态数据成员 ([class.access]),
- (1.3) 没有虚函数([class.virtual]),以及
- (1.4) 没有虚拟、私有或受保护的基类 ([class.mi])。
A,B和U都是聚合类,尽管前者是非联合聚合类,前者不符合条件。
根据[dcl.init.aggr]/5 [强调我的]:
对于非联合聚合,每个不是显式初始化元素的元素都按如下方式初始化:
- (5.1) 如果元素有一个默认的成员初始值设定项([class.mem]),则元素从该初始值设定项进行初始化。
- (5.2) 否则,如果元素不是引用,则从空的初始化列表([dcl.init.list])复制初始化该元素。
- (5.3) 否则,程序格式错误。
如果聚合是联合并且初始值设定项列表为空,则
- (5.4) 如果任何变体成员具有默认成员初始值设定项,则该成员从其默认成员初始值设定项进行初始化;
- (5.5)否则,联合的第一个成员(如果有)是从一个空的初始化列表中复制初始化的。
因此
Run Code Online (Sandbox Code Playgroud)U u{};
是聚合初始化,其结果是联合类的第一个数据成员,即a类型的数据成员A(非联合聚合类),从一个空的初始化列表中复制初始化。由于该x类型的单个数据成员A具有默认成员初始值设定项,因此根据上面的[dcl.init.aggr]/5.1,数据成员x由其默认成员初始值设定项进行初始化。
因此,Clang 是正确的,而 GCC 是错误的。
| 归档时间: |
|
| 查看次数: |
80 次 |
| 最近记录: |