布局兼容类型的并集

Union of layout-compatible types

本文关键字:类型 布局      更新时间:2023-10-16

看看这个代码:

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

注:这是一个后续问题。

是的,这是已定义的行为。首先让我们看看标准对AB有什么规定。[class.pro]/3具有

类S是标准布局类,如果它是

  • 没有非标准布局类(或此类类型的数组(或引用类型的非静态数据成员
  • 没有虚拟函数,也没有虚拟基类
  • 对所有非静态数据成员具有相同的访问控制
  • 没有非标准布局基类
  • 具有任何给定类型的至多一个基类子对象
  • 具有类中的所有非静态数据成员和位字段,以及在同一类中首次声明的基类,以及
  • […](此处所述内容与本案无关(

因此AB都是标准布局类型。如果我们看看[class.mem]/23

两个标准布局结构类型是布局兼容类,如果它们的公共初始序列包括两个类的所有成员和位字段([basic.types](。

和[class.mem]/22

两种标准布局结构类型的公共初始序列是非静态数据成员和位字段按声明顺序排列的最长序列,从每个结构中的第一个这样的实体开始,这样相应的实体就具有布局兼容的类型,要么两个实体都是用no-unique_address属性([dcl.attr.nouniqueaddr](声明的,要么两者都不是,要么这两个实体是宽度相同的位字段,要么都不是位字段。

和[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
}

--结束示例][注意:通过非易失性类型的glvalue读取易失性对象具有未定义的行为([dcl.type.cv](--尾注]

然后,我们假设类具有相同的公共初始序列,布局相同,访问非活动类型的同一成员将被视为访问活动类型的该成员。