看这段代码:
struct A {
short s;
int i;
};
struct B {
short s;
int i;
};
union U {
A a;
B b;
};
int fn() {
U u;
u.a.i = 1;
return u.b.i;
}
是否保证fn()
回报1
?
注意:这是一个后续问题this https://stackoverflow.com/questions/53041630/whats-the-purpose-of-layout-compatible-types.
是的,这是定义的行为。首先让我们看看标准有什么规定A
and B
. [class.prop]/3 https://timsong-cpp.github.io/cppwp/class#prop-3 has
如果满足以下条件,S 类就是标准布局类:
- 没有非标准布局类(或此类类型的数组)类型的非静态数据成员或引用,
- 没有虚函数和虚基类,
- 对所有非静态数据成员具有相同的访问控制,
- 没有非标准布局基类,
- 至多有一个任意给定类型的基类子对象,
- 具有该类及其基类中首先在同一类中声明的所有非静态数据成员和位字段,并且
- [...](这里所说的任何内容在这种情况下都没有任何影响)
So A
and B
都是标准布局类型。如果我们看一下[class.mem]/23 https://timsong-cpp.github.io/cppwp/class#mem-23
如果两个标准布局结构类型的公共初始序列包含两个类的所有成员和位字段 ([basic.types]),则它们是布局兼容的类。
and [class.mem]/22 https://timsong-cpp.github.io/cppwp/class.mem#22
两个标准布局结构类型的公共初始序列是声明顺序中非静态数据成员和位字段的最长序列,从每个结构中的第一个此类实体开始,以便相应的实体具有布局兼容的类型,要么两个实体都使用 no_unique_address 属性 ([dcl.attr.nouniqueaddr]) 进行声明,要么都不是,并且两个实体要么都是具有相同宽度的位字段,要么都不是位字段。
and [class.mem]/25 https://timsong-cpp.github.io/cppwp/class.mem#25
在具有结构类型 T1 的活动成员的标准布局联合中,允许读取结构类型 T2 的另一个联合成员的非静态数据成员 m,前提是 m 是 T1 和 T2 的公共初始序列的一部分;该行为就像 T1 的相应成员被提名一样。 [ 例子:
struct T1 { int a, b; };
struct T2 { int c; double d; };
union U { T1 t1; T2 t2; };
int f() {
U u = { { 1, 2 } }; // active member is t1
return u.t2.c; // OK, as if u.t1.a were nominated
}
— 结束示例 ] [ 注意:通过非易失性类型的左值读取易失性对象具有未定义的行为([dcl.type.cv])。 ——《尾注》]
然后我们知道这些类具有相同的公共初始序列,布局相同,并且访问非活动类型的相同成员被视为访问活动类型的该成员。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)