你能将一个工会会员的价值分配给另一个吗?

时间:2014-02-25 18:21:50

标签: c++ memory language-lawyer unions

请考虑以下代码段:

union
{
   int a;
   float b;
};

a = /* ... */;

b = a;               // is this UB?
b = b + something;

一个工会会员的分配是否有效?

2 个答案:

答案 0 :(得分:4)

不幸的是,我相信这个问题的答案是,对于联合会的这个操作是在C ++中指定的,尽管自我赋值完全没问题。

自我分配是明确定义的行为,如果我们查看草案C ++标准部分1.9 程序执行 15 有以下示例:

void f(int, int);
void g(int i, int* v) {
    i = v[i++]; // the behavior is undefined
    i = 7, i++, i++; // i becomes 9

    i = i++ + 1; // the behavior is undefined
    i = i + 1; // the value of i is incremented

    f(i = -1, i = -1); // the behavior is undefined
}

并在i = i + 1示例中介绍了自我分配。

这里的问题是unlike C89 forward支持C++ it is not clear中的类型双关语。我们只知道:

  

在联合中,至多有一个非静态数据成员可以随时处于活动状态

但由于WG21 UB study group mailing list中的讨论显示这个概念尚不清楚,我们有以下评论:

  

虽然标准使用术语“活动字段”,但它没有定义它

并指出这个非规范性的说明:

  

注意:通常,必须使用显式析构函数调用和放置新运算符来更改联合的活动成员。 - 结束说明

所以我们不得不怀疑:

b = a;

是否使b成为活跃会员?我不知道,我也没有办法用标准草案的任何当前版本证明这一点。

虽然实际上大多数现代编译器(例如gcc)都支持C ++中的类型惩罚,这意味着绕过了活动成员的整个概念。

答案 1 :(得分:0)

我希望除非源变量和目标变量是相同的类型,否则这样的事情将是C中的Undefined Behavior,我认为没有理由期望C ++以不同的方式处理它。给定long long *x,*y;,一些编译器可能会通过生成代码读取所有* y,计算结果并将其存储到* x来处理类似*x = *y >>8;的语句,但编译器可能完全合法地编写复制的代码单独的* y到* x的部分。该标准清楚地表明,如果* x和* y是指向相同类型的同一对象的指针,则编译器必须确保在计算中仍然需要该部分时,该部分值不会被覆盖 ,但编译器不需要在其他情况下处理别名。