Should I use static_cast or reinterpret_cast when casting a void* to whatever
静态类型转换和重新解释类型转换对于将void*转换为另一个指针类型似乎都很好。有没有充分的理由让一个胜于另一个?
- 更好的问题是"如何避免在代码中使用空指针?"这不难做到-我记不起上次用过。
- @很明显,在那之前你从未使用过POSIX线程。
- @用户470379哇……这正是我回答这个问题的原因!观察良好:—)。
使用static_cast:它是最窄的强制转换,精确描述了在这里进行的转换。
有一种误解认为,使用reinterpret_cast将是更好的匹配,因为它意味着"完全忽略类型安全性,只从A到B转换"。
然而,这并不能真正描述reinterpret_cast的效果。相反,reinterpret_cast有许多含义,因为所有这些都认为"reinterpret_cast执行的映射是实现定义的。"[5.2.10.3]
但在从void*到T*的转换的特殊情况下,标准完全定义了映射;即,在不更改地址的情况下,将类型分配给无类型指针。
这是选择static_cast的原因。
此外,还有一个更重要的事实,即每一次使用reinterpret_cast都是非常危险的,因为它将任何东西转换成其他东西(对于指针),而static_cast的限制性要大得多,因此提供了更好的保护级别。这已经把我从错误中救了出来,我不小心试图将一种指针类型强制转换为另一种类型。
这是一个棘手的问题。一方面,Konrad对Reinterpret-Cast的规范定义提出了一个很好的观点,尽管在实践中它可能也做了同样的事情。另一方面,如果在指针类型之间进行强制转换(例如,通过char*在内存中进行索引时,这种情况很常见),静态的u强制转换将生成一个编译器错误,并且无论如何都将强制使用reinterpret u强制转换。
在实践中,我使用了reinterpret_cast,因为它更能描述cast操作的意图。当然,您可以使用不同的运算符来指定指针重新解释(这样可以保证返回的地址相同),但标准中没有。
- "不同的运算符只指定指针重新解释(保证返回相同地址)"拥抱?那个接线员是reinterpret_cast!
- @根据标准,好奇心不是真的。reinterpret不保证使用相同的地址。只有这样,如果您将类型转换重新解释为另一种类型,然后再次返回,您将得到与开始时相同的地址。
我建议总是使用最薄弱的演员阵容。
reinterpret_cast可用于向float投射指针。破坏铸件的结构越多,使用它所需的注意力就越多。
在char*的情况下,我会使用C样式的cast,直到我们有了一些reinterpret_pointer_cast为止,因为它比较弱,其他的都不够。
- "reinterpret"cast可用于将指针强制转换为float。"当然不是!
- 当然可以,好奇心。再次检查标准。
- 你能举个例子吗?
- "再检查一下标准。"你检查过标准吗?
- 对。不过,不知道您所说的示例是什么意思——它的唯一目的是通过预期cookie的指针转发一个float。
- 用什么语法将指针强制转换为浮点?
- 如何将指针投射到浮点?void* p = 0; float f = reinterpret_cast(p);生成error: invalid cast from type ‘void*’ to type ‘float’。我可以投射到int,但不能漂浮。
- 可能是float f = *reinterpret_cast(&p);。
- @在指针之间强制转换的Benvoigt;其中一个恰好是一个浮点指针。
- @野田佳彦:不,它把p的位重新解释为float。使用指向p的指针来完成此操作,但p被强制指向float,而不是float*。
- @本沃伊特:reinterpret_cast正从某个指针(无论p是什么)投射到const float*上。然后取消对该指针的引用以获取浮点值。这确实导致p的位表示被用作float,但reinterpret_cast本身仍将指针类型转换为不同的指针类型。
- @CEMA或不从任何P到float*。从"指向P的指针"—双指针。
- @不好意思,我是说reinterpret_cast的类型是指向p类型的指针。如果p是double,它将从double*铸造成const float*。&p的类型是double*。
- @benvoigt在reinterpret_cast之前的*不是铸件的一部分。它是一个尊重操作员对演员表结果的回复。在此代码中,reinterpret_cast将指针转换为指针。然后在转换完成后取消引用后一个指针。
- @M.M:我知道*是一个独立的运算符,但我的意见仍然是正确的。您是否忽略了reinterpret_cast操作数中的附加&?
- @本沃伊特,我没有忽视它,你的评论是错误的。reinterpret_cast(&p)将指针转换为指针。< >的内容是铸件的结果类型。
- 然后,将一元解引用运算符应用于强制转换的结果。*运算符将const float *转换为float(cast运算符不转换为float)
- @M.M:整个表达式,*reinterpret_cast(&p),确实强迫p到float。我的评论没有错。
- @但本沃伊特的"整个表达"不是演员阵容。表达式由应用于强制转换的取消引用组成。你声称有可能向float投一个指针,这是错误的。该表达式将void **强制转换为const float *,然后使用取消引用操作(不是强制转换)将const float *转换为float。
- @M.M:确实不是演员。我从没叫过它。
- @当有人问"我该如何转换…"时,你给出了这个代码,然后当有人说代码在指针之间转换时,你说"不"
- 在presumed"等等,可以说有人问"投"想要一个转换,但不是一个直接灌注。然后另一个用户的信息claimed铸一void*float*两个A,这是错误的。它void**铸造两float*A A A,两个convert void*float两个A。
我个人的偏好基于这样的代码读写能力:
1 2 3
| void* data = something;
MyClass* foo = reinterpret_cast<MyClass*>(data);
foo->bar(); |
或
1 2 3 4
| typedef void* hMyClass; //typedef as a handle or reference
hMyClass = something;
const MyClass& foo = static_cast<MyClass&>(*hMyClass);
foo.bar(); |
它们最终都是一样的,但是静态的"投射"在中间的软件、应用程序环境中似乎更合适,而重新解释的"投射"更像是在较低级别的库imho中看到的。