你能在具有相同表示的类型之间 reinterpret_cast 吗?

Can you reinterpret_cast between types which have the same representation?

假设我们有两种类型,它们具有相同的表示形式(相同的成员变量和基数 类,顺序相同)。它们之间的 reinterpret_cast 是否有效(即不是 UB)?例如。 reinterpret_castMaryAshley& 有效吗?如果这两种类型是多态的呢?

struct Mary {
    int  m1;
    char m2;
};

struct Ashley {
    int  a1;
    char a2;
};

int TryTwins ()
{
    Mary mary = {};

    Ashley& ashley = reinterpret_cast<Ashley&> (mary);
    ashley.a1 = 1;
    ashley.a2 = 2;

    return mary.m1 + mary.m2;
}

如果我们将一个对象的开头转换为另一种类型,如果我们知道源类型以目标类型的成员变量开头怎么办?例如。这有效吗(即不是 UB)?

struct Locomotive {
    int    engine;
    char   pantograph;
};

struct Train {
    int    engine;
    char   pantograph;
    int*   wagon1;
    int**  wagon2;
    int*** wagon3;
};

int TryTrain ()
{
    Train train = {};

    Locomotive& loc = reinterpret_cast<Locomotive&> (train);
    loc.engine     = 1;
    loc.pantograph = 2;

    return train.engine + train.pantograph;
}

请注意,所有主要编译器都将这些视为有效转换 (live demo)。问题是,C++语言是否允许这样。

[expr.reinterpret.cast]/11:

A glvalue expression of type T1 can be cast to the type “reference to T2” if an expression of type “pointer to T1” can be explicitly converted to the type “pointer to T2” using a reinterpret_­cast. The result refers to the same object as the source glvalue, but with the specified type. [...]

MaryAshley 是对象类型,因此指向它们的指针可以相互转换。现在,我们可以使用 Ashley 类型的 lvalue 来访问底层 Mary 对象。

[basic.lval]/8:

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:

  • the dynamic type of the object,

  • a cv-qualified version of the dynamic type of the object,

  • a type similar to the dynamic type of the object,

  • a type that is the signed or unsigned type corresponding to the dynamic type of the object,

  • a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,

  • an aggregate or union type that includes one of the aforementioned types among its elements or non-static data members (including, recursively, an element or non-static data member of a subaggregate or contained union),

  • a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,

  • a char, unsigned char, or std​::​byte type.

None 其中涵盖了所讨论的案例。 ("Similar" 谈论 cv 资格。)因此,未定义的行为。