请考虑以下代码段:
#include <iostream>
union U{
U(): i(1) {}
int i;
int j = 2; // this default member initializer is ignored by the compiler
};
U u;
int main(){
std::cout << u.i << '\n';
std::cout << u.j << '\n';
}
代码打印(参见live example):
1
1
标准中的哪个部分表示编译器忽略了成员U::j
的默认成员初始值设定项?
请注意,根据[class.union.anon]/4,下面的联合没有编译,这是可以的。因此我期待上面的代码片段也不会编译。
请参阅live example:
union U{
int i = 1;
int j = 2;
};
答案 0 :(得分:7)
标准中的哪个部分表示编译器忽略了成员U :: j的默认成员初始值设定项?
参见C ++ 17 CD中的[class.base.init]第9段子弹9.1。
N.B。您的演示具有未定义的行为,因为联合的活动成员是i
,但您从j
读取。这适用于某些编译器作为非标准扩展,但在ISO C ++中不允许。
答案 1 :(得分:3)
请注意,您正在声明一个union对象,其中所有成员共享相同的内存区域 - 成员变量会转换为相同数据的不同“类型视图”。
因此,当成员i和j有效地存储在同一个内存位置时,您在j上执行的任何初始化(使用初始化程序)都将被构造函数设置i覆盖。
只是为了测试,从构造函数中删除i的初始化:
#include <iostream>
union U{
U() {}
int i;
int j = 2; // this initializes both i & j
};
U u;
int main(){
std::cout << u.i << '\n';
std::cout << u.j << '\n';
}
输出为
2
2
更新: 根据@Ayrosa评论并且只是好奇,我修改了原始片段以使用函数(而不是常量)执行一些初始化以引发副作用。
#include <iostream>
int static someStatic()
{
std::cout << "Initializer was not ignored\n";
return(2);
}
union U{
U(): i(1) {}
int i;
int j = someStatic(); // this default member initializer is ignored by the compiler
};
U u;
int main(){
std::cout << u.i << '\n';
std::cout << u.j << '\n';
}
结果是:
1
1
这意味着编译器忽略了对someStatic()
的调用。