reinterpret_cast cast cost

50
我理解的是,C++ reinterpret_cast 和 C 指针转换只是编译时的功能,并且完全没有性能成本。

这是真的吗?

7个回答

64

这是一个很好的假设。然而,当存在reinterpret_cast<>或C指针转换时,优化器可能会受到限制,无法做出假设。尽管类型转换本身没有任何关联指令,但是最终生成的代码会变慢。

例如,如果你将一个整数转换为指针,优化器可能不知道该指针指向什么。结果就是,它可能会假设通过该指针的写操作可以更改任何变量。这比常见的优化,如在寄存器中存储变量,要慢。


1
我认为“通常不是”不是你对“这是真的吗?”这个问题想要回答的内容。 - Rob Kennedy
2
很不可能。在旧的实现中,优化器只是将变量分配给寄存器。使用“register”会关闭该功能。现在,寄存器分配算法要好得多。例如,它们可以为多个变量重复使用一个寄存器,并仅在其生命周期的一部分将变量分配给寄存器。因此,对于变量的“register”关键字实际上被忽略了。 - MSalters
1
鉴于您关于优化器看到实际写入的评论,这是否意味着仅在指针类型之间进行的reinterpret_cast将被优化为没有运行时成本? - Ephemera
1
@PLPiper:这可能会损害另一种普遍的优化。如果您通过float *写入,然后通过int *读取,则优化器通常可以重新排序两个语句。写入不会影响读取,因为类型不同。但是,如果在int*float*之间有先前的reinterpret_cast,则优化器很可能会采取安全措施。 - MSalters
1
@IngeHenriksen:C语言中的强制类型转换稍微差一些,因为它可以做更多的事情(它可以结合const_castreinterpret_cast)。实际上,我不认为这会比单独使用reinterpret_cast对优化器造成更大的阻碍。出于可读性的原因,请优先考虑使用reinterpret_cast。C语言中的强制类型转换很难发现。 - MSalters
显示剩余5条评论

7

没错。除了在新宽度执行指令时可能会有的性能收益/损失外,没有其他成本。我可以补充一下,这种情况只在极少数情况下才会出现。在我听说过的所有平台上,指针之间的转换都是零成本的,不会对性能产生任何影响。


5
在C++中,C样式的强制类型转换会首先尝试进行static_cast操作,只有在无法进行static_cast时才会执行reinterpret_cast。在多重继承(或将接口转换为具体类型时)static_cast可能会改变指针的值,这个偏移计算可能需要额外的机器指令。但这最多只会涉及一条机器指令,因此影响非常小。

2

是的,这是真的。在运行时会产生成本的转换类型是 dynamic_cast。


4
static_cast可能会有运行时的成本,虽然通常只是一个指针调整或将一种类型转换为另一种类型的代码(例如将int转换为float)。 - Billy ONeal
static_cast 不也会调用用户定义的类型转换吗?而这样做的运行时成本是不可预测的。 - Ben Voigt
对的,static_cast 在类型(而非指针)转换的情况下具有运行时成本。我的观点是,相对于 C 式转换,dynamic_cast 是唯一具有额外运行时成本的转换类型。 - Alex F

2

你说得没错,但是要考虑一下:reinterpret_cast可能意味着设计有问题或者你正在做非常底层的事情。

而dynamic_cast则会有一些开销,因为它需要在运行时查找查找表。


dynamic_cast 更类似于带有运行时检查的 static_cast,而不是 reinterpret_cast。你不能使用 reinterpret_cast 转换多态类型。 - Billy ONeal
2
@Billy ONeal:你可以这样做,但不能实现多态感知。 - Matt Joiner

2

reinterpret_cast不会产生运行时开销.. 但是你必须小心,因为每次使用reinterpret_cast都是实现定义的。例如,将一个char数组重新解释为一个int数组可能会导致目标架构抛出中断,因为不同类型可能具有不同的对齐规则。

先保证正确性,然后再考虑效率。


0

我之前在查看我的汇编代码,使用重新解释将有符号字符转换为无符号字符后,指令的数量增加了大约3或4个。

int main()
{
 signed char i = 0x80;
 (unsigned char&)i >>= 7;
 return i;
}

我在进行无符号字符转换以使用SHL指令而非SAR指令,以便新移位的位移位是0而不是变量i的有符号位值。
编译器仍然并且似乎总是使用SAR指令。但reinterpret类型转换使编译器添加了更多的指令。增加了3到4个指令!
我担心我的Unicode函数将UTF8转换为UTF16字符串比Win32 MultiByteToWideChar()慢近3倍。现在我担心强制转换是主要因素之一。
这是具有讽刺意味的,因为我们使用reinterpret_cast来提高速度。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接