请考虑以下代码段:
union
{
int a;
float b;
};
a = /* ... */;
b = a; // is this UB?
b = b + something;
一个工会会员的分配是否有效?
答案 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是指向相同类型的同一对象的指针,则编译器必须确保在计算中仍然需要该部分时,该部分值不会被覆盖 ,但编译器不需要在其他情况下处理别名。