【问题标题】:Do scalar members in a union count towards the common initial sequence?联合中的标量成员是否计入公共初始序列?
【发布时间】:2018-06-20 21:47:01
【问题描述】:

在下面的union U中,如果a或b是活动成员,是否定义了访问c的行为?

struct A{
    int a;
};
struct B{
    int a;
    double b;
};
union U{
    A a;
    B b;
    int c;
};

在[class.union] 中,该标准定义了一些规则以使union 的使用更容易(强调我的):

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

我对 struct 这个词很感兴趣。像int 这样的标准布局标量即使不是结构也算数吗?

  • 我上面的union U 确实是[class] 之后的“标准布局”联合,基本上说它需要是一个使用union 关键字的标准布局类,因为我们只使用标量(标准布局类型),它通过了。

  • 这些结构显然共享一个common initial sequence,它由第一个int 成员组成,但尚不清楚是否可以将基本类型考虑用于常见的初始序列。

    • [class.union] 还说“每个非静态数据成员都被分配,就好像它是结构的唯一成员一样。”我认为这提供了它被定义的证据。
  • 最后,标准布局结构不允许在开头有填充([class.mem]),联合的成员是pointer interconvertible,所以标准告诉我们标准布局结构中的int元素,并且联合中的非静态int c 保证对齐。

【问题讨论】:

  • 普通的初始序列只定义为类类型的属性。访问是否有效我就不讨论了,但如果是,那肯定不是按照常见的初始顺序保证。
  • @StoryTeller:我刚刚用标准的另一个摘录更新了这个问题,关于如何分配非静态数据成员,就好像它们是 struct 的唯一成员一样,这意味着int在union 的上下文中,可以认为是标准布局结构。
  • 我会告诉你更多。这些成员是pointer-interconvertible。但我不确定是否可以访问“非活动”成员。我敢打赌,不会。
  • @StoryTeller:我不清楚当你说“非活跃成员”时你是指int c,还是包括B b(假设A a是活跃成员)跨度>
  • 我的意思是任何没有最后一次写信的工会成员。通俗地说,与 [class.union]/1 定义的相反。所以是的,c 和 b(尽管在这种特殊情况下,c 很有趣)。

标签: c++ language-lawyer c++17 unions


【解决方案1】:

struct A 和 struct B 是:

  • 包含在标准布局union U中,
  • 标准布局结构,以及
  • 共享一个共同的初始序列。

因此,它们满足句子“如果标准布局联合包含多个共享公共初始序列的标准布局结构......”中的描述。

同样在联合中的int c 既不是这样的结构,也不是这样的结构。所以这句话并不是告诉你可以写信给c并检查a.a或b.a,也不是告诉你可以写信给a.a或b.a并检查c。

这意味着c 不是您可以检查的常见初始序列的一部分。但它也不会破坏struct A 和struct B 的常见初始序列。

关于文本“每个非静态数据成员被分配就好像它是结构的唯一成员一样”,该标准在这里的语言有点草率。分配通常是指获取或保留存储,但这种用法似乎是指在给定存储中布置对象的字节。我在 C++ 标准中没有看到正式的定义(但我没有看太难),但我确实找到了类似的用途。所以我认为它的意思是每个非静态数据成员的布局就像它是唯一的成员一样。

这意味着指向这些联合成员中的任何一个的指针与指向任何其他联合成员的指针指向相同的位置。这可能意味着指向一个的指针可以转换为指向另一个的指针。但是,它不会授予您违反严格混叠规则的许可。即使x 是指向c 的指针并且y 是指向a 或a.a 的指针,您也不能使用*x 访问c 而a 是最后写入的成员或使用*y 而c 是最后写入的成员。

【讨论】:

  • 我认为关于别名的评论让一切变得不同。即使保证内存对齐,当结构之一处于活动状态时访问int 成员也会违反别名。
猜你喜欢
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-10
  • 1970-01-01
  • 2014-04-15
  • 1970-01-01
相关资源
最近更新 更多