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;
}