【问题标题】:Which cast to use; static_cast or reinterpret_cast?使用哪个演员; static_cast 还是 reinterpret_cast?
【发布时间】:2011-05-27 10:42:16
【问题描述】:
int i = 1000;
void *p = &i;

int *x = static_cast<int*>(p);
int *y = reinterpret_cast<int*>(p);

应该使用哪种类型转换从void* 转换为int*,为什么?

【问题讨论】:

标签: c++ casting


【解决方案1】:

static_cast 前提是你知道(根据你的程序设计)指向的东西确实是int

static_cast 旨在反转任何隐式转换。您已隐式转换为void*,因此您可以(并且应该)使用static_cast 转换回来如果您知道您确实只是在反转之前的转换。

有了这个假设,没有任何东西被重新解释 - void 是一个不完整的类型,这意味着它没有值,所以你在任何时候都不会将存储的 int 值解释为“无效”或存储的“无效值”作为int。 void* 只是一种丑陋的说法,“我不知道类型,但我会将指针传递给其他知道的人”。

reinterpret_cast 如果您省略了一些细节,这意味着您实际上可能正在使用不同于编写该类型的类型读取内存,请注意您的代码的可移植性有限。

顺便说一句,在 C++ 中以这种方式使用 void* 指针的理由并不多。 C 风格的回调接口通常可以替换为模板函数(对于任何类似于标准函数 qsort 的东西)或虚拟接口(对于任何类似于注册侦听器的东西)。如果您的 C++ 代码使用一些 C API,那么您当然没有太多选择。

【讨论】:

  • 就我而言,我会选择 static_cast。
  • 如果您不知道该类型是 int 或正确对齐,您应该使用 reinterpret_cast?
  • @Martin:这是一个问题还是一个声明?这意味着如果您要重新解释,则应该使用reinterpret_cast,因此这将是特定于实现的。在某些实现中,int 的对齐要求为 1,因此不会出现该问题。在指针可能未对齐的另一个实现中,相同的代码将超出其“有限的可移植性”。在另一个实现中,由于严格的别名规则,您根本无法键入双关语(char 除外)。
【解决方案2】:

在当前的 C++ 中,您不能像在该代码中那样使用 reinterpret_cast。对于 void*int* 的转换,您只能使用 static_cast(或等效的 C 样式转换)。

对于不同函数类型指针之间或不同对象类型指针之间的转换,您需要使用reinterpret_cast

在 C++0x 中,reinterpret_cast&lt;int*&gt;(p) will be equivalentstatic_cast&lt;int*&gt;(p)。它可能已包含在下一个 WP 中。

认为reinterpret_cast&lt;T*&gt;(p) 会将p 的位解释为代表T* 是一种误解。在这种情况下,它将使用p 的类型读取p 的值,然后将该值转换为T*。一个实际的type-pun 使用类型T* 的表示直接读取p 的位,仅在您强制转换为引用类型时才会发生,如reinterpret_cast&lt;T*&amp;&gt;(p)

据我所知,所有当前的编译器都允许从 void* 转换为 reinterpret_cast,并且其行为等同于相应的 static_cast,即使当前 C++03 中不允许这样做。被拒绝时所破坏的代码数量并不有趣,因此他们没有动机禁止它。

【讨论】:

  • -1 表示“在当前的 C++ 中,您不能像在该代码中那样使用 reinterpret_cast”。演员表是允许的,但大概您打算写出该标准并未正式保证该效果。而且它没有直接保证,它是“未指定的”。但是,对于 static_castreinterpret_cast 转换 T* -> void* -> T* 保证产生原始值。并且由于这必须适用于每个指针值,为了阻止它,一个不正当的编译器必须记录一些系统性的不必要的更改,比如在 reinterpret_cast from void* 时加 1,反之亦然。没有人会买它。
  • @Alf 不允许强制转换。 5.2.10/1 说“下面列出了可以使用 reinterpret_cast 显式执行的转换。不能使用 reinterpret_cast 显式执行其他转换。”。没有列出允许 void* -> T*T* -> void* 的转换。
  • @Johannes:首先,这是错误的:它是§5.2.10/7,结合了 void* 的对齐信息。我不记得后者是在哪里直接指定的,如果是的话,但是static_cast 的规则暗示了它,§5.2.9/10。其次,您引用的 5.2.10/1 与 §9.2/17 直接矛盾。没有正式的缺陷报告总是让我感到惊讶,但即使不存在这种不一致,即使 5.2.10/1 很好,§5.2.10/7 + §5.2.9/10 说你错了这。对不起。或者,咧嘴一笑。 :-)
  • @Alf 请注意我们在 cmets 中关于这个答案的对话:stackoverflow.com/questions/4107907/…
  • @Alf 5.2.10/7 不允许将指针转换为 void 从或指向任何东西。 void 不是对象类型。为什么 5.2.10/1 与 9.2/17 矛盾?
【解决方案3】:
【解决方案4】:

从你问题的语义来看,我会重新解释,因为那是你实际做的。

【讨论】:

  • 我不同意,因为在这个简单的例子中,显然知道 void* p 实际上指向一个整数,只需要一个 static_cast。重新解释演员表的风险更大,因为如果有人对分配 void* p 的代码进行混淆,它将允许将来出现一些非常奇怪的行为。
  • @Paul:如果有人对p 的分配感到不满,static_cast 肯定会出现同样奇怪的行为,例如从指针分配到小于int 的东西。我认为使用static_cast 的原因是为了传达转换的意图(即它不是supposed 重新解释),但演员本身实际上并没有阻止重新解释的发生,因为@ 987654325@ 可以与任何对象指针类型相互转换。
  • @Steve,我明白了,感谢您的澄清。我对这东西的理解有些模糊,因为我时不时只写C++,但基本的注​​释是re:static_cast更合适。
猜你喜欢
  • 1970-01-01
  • 2014-03-01
  • 2011-04-04
  • 2016-05-28
  • 2013-02-18
  • 2010-11-14
  • 2013-10-18
  • 1970-01-01
  • 2010-09-06
相关资源
最近更新 更多