§9.5.1 状态:
[ 笔记: 一份特别保障 是为了简化联合的使用:如果一个标准布局联合包含多个标准布局 共享一个公共初始序列的结构( 9.2 ), 如果这个标准布局联合类型的对象 包含标准布局结构之一,允许检查任何的公共初始序列 标准布局结构成员;看 9.2 . ——尾注 ]
其他地方有一些问题围绕非类类型和包含该类型成员的标准布局结构是否兼容布局并包含在本保证中。
以下代码是否显示未定义的行为?
struct S {
int a;
};
union U {
int a;
S b;
};
int main() {
U foo;
foo.a = 3;
return foo.b.a;
}
是的,行为未定义。所有 C++ 标准版本都是这种情况。
例如,在编写此问题时有效的标准 C++14 中,可以在 [class.mem]/18 中找到特殊的“公共初始序列”规则。 (问题中引用的注释来自 [class.union]/1,是非规范的;C++ 标准中的注释始终是非规范的。)[class.mem]/18 说:
如果标准布局联合包含两个或多个共享公共初始序列的标准布局结构, 并且如果标准布局联合对象当前包含这些标准布局结构之一,则允许 检查其中任何一个的公共初始部分。两个标准布局结构共享一个共同的首字母 如果对应的成员具有布局兼容的类型并且成员都不是位域或 对于一个或多个初始成员的序列,两者都是具有相同宽度的位域。
U
是一个标准布局联合,但它不包含两个标准布局结构。它包含一个具有标准布局结构类型b
的成员S
和一个非结构类型a
的成员int
。 “公共初始序列”仅为两个标准布局结构定义; a
与 b
没有共同的初始序列。
因此,试图读取
foo.b.a
的值就是试图读取一个不存在的对象的值,因为 foo.b
不存在,因为 b
成员不活跃。这是[basic.life]/6下的UB