我正在将一堆代码转换为使用 C++ 风格的转换(在 -Wold-style-cast
的帮助下)。我并不完全相信它对原始变量的使用,但总的来说我是 C++ 风格转换的新手。
一个问题发生在一些字节序转换代码中。当前代码如下所示:
#define REINTERPRET_VARIABLE(VAR,TYPE) (*((TYPE*)(&VAR)))
//...
uint16_t reverse(uint16_t val) { /*stuff to reverse uint16_t*/ }
int16_t reverse( int16_t val) {
uint16_t temp = reverse(REINTERPRET_VARIABLE(val,uint16_t));
return REINTERPRET_VARIABLE(temp,int16_t);
}
现在,字节顺序并不关心签名。因此,要反转 int16_t
,我们可以完全将其视为 uint16_t
以达到反转的目的。这建议这样的代码:
int16_t reverse( int16_t val) {
return reinterpret_cast<int16_t>(reverse(reinterpret_cast<uint16_t>(val)));
}
但是,如 this 中所述特别是 this问题是,reinterpret_cast
需要引用或指针(除非它正在转换为自身)。这表明:
int16_t reverse( int16_t val) {
return reinterpret_cast<int16_t&>(reverse(reinterpret_cast<uint16_t&>(val)));
}
这是行不通的,因为正如我的编译器告诉我的那样,外部转换需要一个左值。要解决此问题,您需要执行以下操作:
int16_t reverse( int16_t val) {
uint16_t temp = reverse(reinterpret_cast<uint16_t&>(val));
return reinterpret_cast<int16_t&>(temp);
}
这和原来的代码差别不大,临时变量的存在也是同样的道理,但是给我提了四个问题:
- 为什么
reinterpret_cast
甚至需要临时的?我可以理解一个愚蠢的编译器需要有一个临时的来支持REINTERPRET_VARIABLE
的指针肮脏,但是reinterpret_cast
应该只是重新解释位。这与 RVO 有冲突吗? - 要求该临时值是否会导致性能下降,或者编译器是否有可能确定该临时值真的应该只是返回值?
- 第二个
reinterpret_cast
看起来像是在返回一个引用。由于函数返回值不是引用,所以我很确定这没问题;返回值将是一个拷贝,而不是引用。但是,我仍然想知道转换为引用到底意味着什么?它在这种情况下是合适的,对吗? - 还有其他我应该注意的性能影响吗?我猜
reinterpret_cast
会(如果有的话)更快,因为编译器不需要弄清楚这些位应该被重新解释——我只是告诉它他们应该?
最佳答案
temp
是必需的,因为&
(地址)运算符在下一行应用于它。此运算符需要一个左值(要获取其地址的对象)。我希望编译器能够优化它。
reinterpret_cast<T&>(x)
与* reinterpret_cast<T *>(&x)
相同, 它是一个左值,指定与x
相同的内存位置占据。请注意,表达式的类型永远不是引用;但转换为T&
的结果,或使用*
运算符是一个左值。我预计不会出现任何性能问题。
这段代码没有严格的别名问题,因为它允许将整数类型别名为相同类型的有符号或无符号变体。但是您建议代码库中充满了重新解释的转换,因此您应该注意其他地方是否存在严格的别名违规行为,也许可以使用 -fno-strict-aliasing
进行编译。直到解决为止。
关于c++ - reinterpret_cast 右值和优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25691986/