根据ISO C ++委员会的上次会议,将在C ++ 20标准中引入bit-cast。
我知道reinterpret_cast
由于type aliasing rules不适合该工作,但我的问题是为什么他们为什么不选择扩展reinterpret_cast
来像位序列表示那样对待对象并愿意将此功能作为一种新的语言结构来提供?
答案 0 :(得分:13)
好吧,有一个明显的原因:因为它无法完成bit_cast
所做的所有事情。即使在我们可以在编译时分配内存的C ++ 20世界中,reinterpret_cast
函数中也禁止constexpr
。 bit_cast
的明确目标之一是能够在编译时执行以下操作:
此外,由于
constexpr
本身不是memcpy
,因此目前无法实现constexpr
位广播功能。将建议的功能标记为constexpr
并不需要或阻止memcpy
成为constexpr
,但是需要编译器支持。这样一来,实施人员就可以自由使用自己的内部解决方案(例如LLVM具有bitcast
操作码)。
现在,您可以说您可以将reinterpret_cast
的这种特定用法扩展到constexpr
上下文。但这使规则变得复杂。您不仅要记住reinterpret_cast
不能在constexpr
代码期内使用,还必须记住reinterpret_cast
不能使用的特定形式。
此外,还有一些实际问题。即使您想走reinterpret_cast
路线,std::bit_cast
还是一个库函数。通过委员会获得图书馆功能总是比语言功能容易,即使它会得到一些编译器支持。
然后是更多主观的东西。 reinterpret_cast
通常被认为是一种固有的危险操作,表明以某种方式“欺骗”了类型系统。相反,bit_cast
不是。它正在生成一个新对象,就像通过从现有对象复制其值表示形式一样。这是一个低级工具,但不是与类型系统混淆的工具。因此,拼写“安全”操作就像拼写“危险”操作一样奇怪。
实际上,如果您以相同的方式拼写它们,则会开始引起人们对为什么定义合理的疑问:
float f = 20.4f;
int i = reinterpret_cast<int>(f);
但是这有点不好:
float f = 20.4f;
int &i = reinterpret_cast<int &>(f);
可以肯定,语言律师或熟悉严格别名规则的人会理解为什么后者不好。但是对于外行人来说,如果可以使用reinterpret_cast
进行位转换,则不清楚为什么使用reinterpret_cast
转换指针/引用并将现有对象解释为错误是错误的。转换的类型。
不同的工具应拼写不同。
答案 1 :(得分:-3)
在现代的高级语言性质,编译器对C和C ++语言标准的严格解释与可以使用reinterpret_cast
将一堆字节重新解释为另一个对象的概念之间存在根本的不匹配。请注意,在大多数情况下,所谓的“严格别名”规则甚至不能用于取消重新解释字节的任何尝试的资格,因为该代码最初并没有定义行为:reinterpret_cast<float*>(&Int)
甚至都不是指向一个浮点对象,它是一个指向恰好具有错误类型的整数的指针。您不能取消引用它,因为在该位置没有创建浮动对象。如果有一个,它的生命就不会开始;如果它的生命周期已经开始,那么它将不会被初始化。
如果您在此处没有合适的浮点对象,那么恰好不能表示正好代表有效浮点位模式的字节。
有效的非null指针不仅仅是碰巧正确对齐的区域起始地址的类型化值; 非空有效指针指向特定对象(或指向数组末尾或一个对象的琐碎“数组”之后的指针)。
我什至看不到“严格别名”批准的标量重新解释类型转换(有符号/无符号混合)可能是有效的,因为该地址上存在无符号(分别为无符号)整数(并且编译器显然不能使用也可以是未签名(已签名)的原始值。
无论哪种方式,C ++的设计都是错误的,因为它混合了不同的语言(有些语言级别很低,有些语言级别很高)并且被严重破坏了。