检查非活动联合成员,共同的初始序列

问题描述 投票:5回答:1

这个问题是基于this

考虑以下:

struct Hdr { int type; };
struct A { Hdr h; };
union Big {
   Hdr h;
   A a;
};

并且假设对Big big我们知道big.a是联盟的活跃成员。是否可以访问big.h.type未定义的行为?

我认为确实是UB,基于:

class.union

... [注意:为了简化联合的使用,我们做了一个特殊的保证:如果标准布局联合包含几个共享一个公共初始序列([class.mem])的标准布局结构,如果是非此标准布局联合类型的对象的静态数据成员是活动的并且是标准布局结构之一,允许检查任何标准布局结构成员的公共初始序列;见[class.mem]。 - 结束说明]

我们有一个标准的布局联合,它有标准的布局成员结构但是理解它,common initial sequenceHdrA是空的,即使A的第一个数据成员是Hdr的类型。

我是对的,这是UB吗?如果没有,我误解了哪个常见的初始序列,以便定义访问big.h.type

c++ language-lawyer union
1个回答
4
投票

我认为你的解释没有错。

根据你的引用,只有当AHdr共享一个包含Hdr::type的共同初始序列时,才能明确定义。

引用定义公共初始序列的规则:

[class.mem]两个标准布局struct([class.prop])类型的公共初始序列是声明顺序中非静态数据成员和位字段的最长序列,从每个中的第一个这样的实体开始结构,使相应的实体具有布局兼容类型......

因此,AHdr的第一个成员是常见的,如果他们 - 即intHdr - 是布局兼容的类型。这是在中指定的

[basic.types]两种类型cv1 T1和cv2 T2是布局兼容类型,如果T1和T2是相同类型(它们不是同一类型),布局兼容枚举(它们不是枚举)或布局兼容标准-layout类类型(其中只有一个是类类型)。

由于没有适用,intHdr不是布局兼容的,因此AHdr的常见初始序列是空的,因此没有引用特殊保证适用的成员。


您可以使用包装器来绕过规则的微妙之处:

union Big {
   struct {
       Hdr h;
   } w;
   A a;
} big;

在这里,即使big.w.h.type处于活动状态,访问big.a也会很明确。附:匿名结构在这里很好,使包装器不可见。不幸的是,这些在标准C ++中是不正确的。

© www.soinside.com 2019 - 2024. All rights reserved.