请看这个片段:
#include <new>
struct Storage {
int value;
Storage() : value(0) { }
};
struct Field {
void set(int v) {
reinterpret_cast<Storage *>(this)->value = v;
}
};
union Foo {
Storage storage;
Field field;
Foo() {
new(&storage) Storage;
}
};
int main() {
Foo f;
f.field.set(1);
}
在main
中,f
有活跃成员storage
。然后,在另一个成员(field
)上,有一个函数调用(set
),它将this
强制转换为活动成员的类型。
此代码是否有UB?
答案 0 :(得分:3)
对f.field.set
的调用违反了[class.mfct.non-static] p2:
如果为类型为
X
的类型的对象或从X
派生的类型调用类X
的非静态成员函数,则行为未定义
当您没有set
类型的对象时,您正在调用类Field
的成员函数Field
。
答案 1 :(得分:3)
此程序具有未定义的行为,因为您可能无法调用当前不活动的对象的非静态成员函数。 C ++ 14 [basic.life] / 6:
类似地,在对象的生命周期开始之前但在对象将占用的存储之后已经分配,或者在对象的生命周期结束之后以及在重用或释放对象占用的存储之前,任何glvalue引用原始对象可能只能以有限的方式使用....如果出现以下情况,程序有不确定的行为:
...
glvalue用于访问非静态数据成员或调用对象的非静态成员函数
...