正在使用reinterpret_cast(在非活动成员中)强制转换为联合 UB 的活动成员

Is using reinterpret_cast (in a non-active-member) to cast to the active member of an union UB?

本文关键字:成员 转换 活动 UB reinterpret cast 非活动      更新时间:2023-10-16

看看这个片段:

#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 吗?

f.field.set的调用违反了 [class.mfct.non-static]p2:

如果为非

类型X的对象调用类X的非静态成员函数,或者不是从X派生的类型,则行为是未定义的。

当您

没有类型 Field 的对象时,您正在调用类set的成员函数Field

此程序具有未定义的行为,因为您不能调用当前未处于活动状态的对象的非静态成员函数。 C++14 [basic.life]/6:

类似地,在对象的生存期开始之前,但在分配了对象将占用的存储之后

,或者在对象的生存期结束之后,在对象占用的存储被重用或释放之前,任何涉及原始对象的glvalue都可以使用,但只能以有限的方式使用。 在以下情况下,程序具有未定义的行为:

  • glvalue 用于访问非静态数据成员或调用对象的非静态成员函数