为什么没有reinterpret_cast强制copy_n用于相同大小类型之间的转换?

时间:2015-02-24 13:53:57

标签: c++ casting binary copy reinterpret-cast

根据cppreference.comreinterpret_cast

  

通过重新解释基础位模式在类型之间进行转换。

但等等,这是谎言因为它只适用于这些情况:

  

当对T1类型的对象的指针或引用为reinterpret_cast(或C样式转换)指针或对不同类型T2的对象的引用时,成功,但只有当T1T2都是标准布局类型且以下之一为真时,才能访问结果指针或引用:

    < li> T2是对象的(可能是cv限定的)动态类型   
  • T2T1都是(可能是多级,可能是每个级别的cv限定)指向同一类型的指针T3
  •   
  • T2是对象动态类型的(可能是cv限定的)有符号或无符号变体
  •   
  • T2是聚合类型或联合类型,它将上述类型之一保存为元素或非静态成员(包括递归地,包含联合的子聚合和非静态数据成员的元素) :这样可以安全地从结构的第一个成员和union的元素转换为包含它的struct / union。
  •   
  • T2是(可能是cv限定的)对象动态类型的基类
  •   
  • T2charunsigned char

根据该清单,一个非法的例子是:

auto foo = 13LL;
auto bar = reinterpret_cast<double&>(foo);

因此,唯一可以接受的方法是复制内存:

auto foo = 13LL;
double bar;

copy_n(reinterpret_cast<char*>(&foo), sizeof(foo), reinterpret_cast<char*>(&bar));

我的问题是,为什么reinterpret_cast没有为我处理?或者还有其他可用的东西,所以我不必跳过这个箍?

2 个答案:

答案 0 :(得分:3)

  

为什么reinterpret_cast没有为我处理?

一个原因是未指定大小,对齐和位表示,因此这种转换不可移植。但是,这并不能证明行为未定义,只是实现定义。

通过使其未定义,允许编译器假定不相关类型的表达式不访问同一对象,这可以允许更好的优化。例如,在以下内容中:

int   & i = something();
float & f = something_else();

const int i1 = i;
f = 42;
const int i2 = i;

编译器可以假设i1i2都具有相同的值(i未被f赋值),并将它们优化为单个常量。打破这个假设会导致不确定的行为。

  

或者是否有其他可用的东西,所以我不必跳过这个箍?

复制字节是将一种对象类型重新解释为无关类型的唯一明确定义的方法。

使用reinterpret_cast或联合的别名有时可能会起作用(假设大小等匹配),但如果优化器因未定义的行为变得过于聪明,可能会让你失望。

答案 1 :(得分:1)

主要是对reinterpret_cast的限制(未被cppreference网站完全捕获)是因为

  • 对齐问题和
  • 陷阱表示。

对于假设的reinterpret_cast到数字值,可以通过截断或零扩展轻松处理不同的大小,因为无论如何都会进入危险的位级域,因此这不是问题。< / p>

使用memcpycopy_n解决对齐问题,但您仍然可能成为陷阱表示的受害者。这意味着使用结果值可能会爆炸。在某些平台上,对于某些值。


请注意,任何特定编译器都可以并且通常会扩展标准的任何保证。

通常,仅仅依靠标准来瞄准比可以拥有的便携性少一点是个好主意。

例如,当你不能假设一个字节是8位时,事情变得很复杂。做出这种假设会降低可移植性。但是支持的平台仍然很大。