C++ 您能否重新解释具有相同表示形式的类型之间的类型转换?

C++ 您能否重新解释具有相同表示形式的类型之间的类型转换?,c++,language-lawyer,undefined-behavior,strict-aliasing,reinterpret-cast,C++,Language Lawyer,Undefined Behavior,Strict Aliasing,Reinterpret Cast,假设我们有两种类型,它们具有相同的表示形式(相同的成员变量和基类,顺序相同)。重新解释他们之间的转换是否有效(即非UB)?例如,从Mary到Ashley&重新解释演员阵容是否有效?如果这两种类型是多态的呢 struct Mary { int m1; char m2; }; struct Ashley { int a1; char a2; }; int TryTwins () { Mary mary = {}; Ashley& as

假设我们有两种类型,它们具有相同的表示形式(相同的成员变量和基类,顺序相同)。
重新解释他们之间的转换是否有效(即非UB)?例如,
Mary
Ashley&
重新解释演员阵容是否有效?如果这两种类型是多态的呢

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;
}
struct-Mary{
int m1;
焦m2;
};
阿什利结构{
int a1;
字符a2;
};
int TryTwins()
{
玛丽{};
艾希礼和艾希礼= RealTytCaseC.)问题是,C++语言是否允许这样做。

类型为
T1
的glvalue表达式可以强制转换为类型“reference” 如果“指向
T1
”类型的表达式可以显式 使用
重新解释
转换为“指向
T2
”类型。 结果引用与源glvalue相同的对象,但具有 指定的类型。[…]

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

:

如果程序试图通过访问对象的存储值 行为为以下类型之一以外的glvalue 未定义:

  • 对象的动态类型

  • 对象动态类型的cv限定版本

  • 与对象的动态类型类似的类型

  • 与对象的动态类型相对应的有符号或无符号类型

  • 一种类型,它是与对象的动态类型的cv限定版本相对应的有符号或无符号类型

  • 在其元素或非静态数据成员中包含上述类型之一的聚合或联合类型(包括, 递归地,子集合或子集合的元素或非静态数据成员 包含的联盟)

  • 是对象动态类型的基类类型(可能是cv限定的)

  • 字符
    无符号字符
    标准字符​::​字节
    类型


所有这些都不包括所讨论的案例。(“类似”指的是简历资格。)因此,未定义的行为。

我同意,尽管可以认为
ashley.a1
int
类型的左值,用于访问对象
mary.m1
,该对象是
int
类型的对象。显然,表达式
ashley.a1
访问存储的
ashley.a1
是其成员的整个对象的值,尽管标准没有明确说明这一点out@LanguageLawyer好吧,主要的编译器供应商都持这种立场,那么我们真的可以说这是一种误解吗?该标准旨在编纂社区一致同意的实践;它同样可以被认为是错误的说明标准不明确和/或有缺陷。@M.M:如果我访问
mary.m1
(这是一个
int
)通过一个
int&
,它被初始化为
ashley.a1
?。这样表达式
ashley.a1
就不用于访问内存。它的地址只被使用。这会改变什么吗?@M.M:C社区从来没有就一组规则达成一致,部分原因是不可能指定一组可以不要让一些任务变得不必要的困难,或者不需要为这些任务提供的实现是不必要的低效。@好奇怪,它猜是从C STD粘贴的,直到最近才被审查。C++中的STD中有大量的BS需要大量的改写。注释不用于扩展讨论;翻转已经完成。
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;
}