简体   繁体   English

将 void* 转换为任何内容时,我应该使用 static_cast 还是 reinterpret_cast

[英]Should I use static_cast or reinterpret_cast when casting a void* to whatever

Both static_cast and reinterpret_cast seem to work fine for casting void* to another pointer type. static_castreinterpret_cast似乎都可以很好地将void*转换为另一种指针类型。 Is there a good reason to favor one over the other?有充分的理由偏爱其中之一吗?

Use static_cast : it is the narrowest cast that exactly describes what conversion is made here. 使用static_cast :它是最精确的演员,它准确地描述了在这里进行的转换。

There's a misconception that using reinterpret_cast would be a better match because it means “completely ignore type safety and just cast from A to B”. 有一种误解,即使用reinterpret_cast会更好地匹配,因为它意味着“完全忽略类型安全并且只是从A转换为B”。

However, this doesn't actually describe the effect of a reinterpret_cast . 但是,这实际上并没有描述reinterpret_cast的效果。 Rather, reinterpret_cast has a number of meanings, for all of which holds that “the mapping performed by reinterpret_cast is implementation-defined.” [5.2.10.3] 相反, reinterpret_cast有许多含义,因为所有这些含义都认为“ reinterpret_cast执行的映射是实现定义的。”[5.2.10.3]

But in the particular case of casting from void* to T* the mapping is completely well-defined by the standard; 但是在从void*T*的特定情况下,映射完全由标准定义; namely, to assign a type to a typeless pointer without changing its address. 即,在不改变其地址的情况下为无类型指针分配类型。

This is a reason to prefer static_cast . 这是首选static_cast的原因。

Additionally, and arguably more important, is the fact that every use of reinterpret_cast is downright dangerous because it converts anything to anything else really (for pointers), while static_cast is much more restrictive, thus providing a better level of protection. 此外,可以说更重要的是,每次使用reinterpret_cast都是非常危险的,因为它将任何东西转换为其他任何东西(用于指针),而static_cast则更具限制性,从而提供更好的保护级别。 This has already saved me from bugs where I accidentally tried to coerce one pointer type into another. 这已经让我免于我偶然试图将一个指针类型强制转换为另一个指针类型的错误。

The static_cast is more appropriate for converting a void* to a pointer of some other type. static_cast更适合将void*转换为其他类型的指针。

static_cast is the cast of choice when there is a natural, intuitive conversion between two types that isn't necessarily guaranteed to work at runtime.当两种类型之间存在自然、直观的转换但不一定保证在运行时工作时, static_cast是首选转换。 For example, you can use static_cast to convert base class pointers to derived class pointers, which is a conversion that makes sense in some cases but can't be verified until runtime.例如,您可以使用static_cast将基类指针转换为派生类指针,这种转换在某些情况下是有意义的,但要到运行时才能验证。 Similarly, you can use static_cast to convert from an int to a char , which is well-defined but may cause a loss of precision when executed.同样,您可以使用static_castint转换为char ,它定义明确,但在执行时可能会导致精度损失。

reinterpret_cast , on the other hand, is a casting operator designed to do conversions that are fundamentally not safe or not portable.另一方面, reinterpret_cast是一个转换运算符,旨在进行从根本上不安全或不可移植的转换。 For example, you can use reinterpret_cast to convert from a void * to an int , which will work correctly if your system happens to have sizeof (void*)sizeof (int) .例如,您可以使用reinterpret_castvoid *转换为int ,如果您的系统碰巧有sizeof (void*)sizeof (int) ,这将正常工作。 You can also use reinterpret_cast to convert a float* to an int* or vice-versa, which is platform-specific because the particular representations of float s and int s aren't guaranteed to have anything in common with one another.您还可以使用reinterpret_castfloat*转换为int*或反之,这是特定于平台的,因为不能保证float s 和int s 的特定表示彼此有任何共同之处。

In short, if you ever find yourself doing a conversion in which the cast is logically meaningful but might not necessarily succeed at runtime, avoid reinterpret_cast .简而言之,如果您发现自己进行的转换在逻辑上有意义但在运行时可能不一定成功,请避免使用reinterpret_cast static_cast is a good choice if you have some advance knowledge that the cast is going to work at runtime, and communicates to the compiler "I know that this might not work, but at least it makes sense and I have a reason to believe it will correctly do the right thing at runtime." static_cast是一个不错的选择,如果你预先知道转换将在运行时工作,并与编译器通信“我知道这可能行不通,但至少它是有道理的,我有理由相信它会在运行时正确地做正确的事。” The compiler can then check that the cast is between related types, reporting a compile-time error if this isn't the case.然后编译器可以检查转换是否在相关类型之间,如果不是这种情况则报告编译时错误。 Using reinterpret_cast to do this with pointer conversions completely bypasses the compile-time safety check.使用reinterpret_cast通过指针转换来完成此操作完全绕过了编译时安全检查。

There are a few circumstances where you might want to use a dynamic_cast instead of a static_cast , but these mostly involve casts in a class hierarchy and (only rarely) directly concern void* .在某些情况下,您可能希望使用dynamic_cast而不是static_cast ,但这些情况大多涉及类层次结构中的强制转换,并且(很少)直接涉及void*

As for which one is preferred by the spec, neither is overly mentioned as "the right one to use" (or at least, I don't remember one of them being mentioned this way.) However, I think the spec wants you to use static_cast over reinterpret_cast .至于规范更喜欢哪一个,都没有被过度提及为“正确使用”(或者至少,我不记得其中一个被这样提及。)但是,我认为规范希望你使用static_cast而不是reinterpret_cast For example, when using a C-style cast, as in例如,当使用 C 风格的转换时,如

A* ptr = (A*) myVoidPointer;

The order of casting operators that's tried always tries to use a static_cast before a reinterpret_cast , which is the behavior you want since reinterpret_cast isn't guaranteed to be portable.尝试的转换运算符的顺序总是尝试在reinterpret_cast之前使用static_cast ,这是您想要的行为,因为不能保证reinterpret_cast是可移植的。

This is a tough question. 这是一个棘手的问题。 On the one hand, Konrad makes an excellent point about the spec definition for reinterpret_cast , although in practice it probably does the same thing. 一方面,Konrad对reinterpret_cast的规范定义提出了一个很好的观点,尽管在实践中它可能做同样的事情。 On the other hand, if you're casting between pointer types (as is fairly common when indexing in memory via a char*, for example), static_cast will generate a compiler error and you'll be forced to use reinterpret_cast anyway. 另一方面,如果你在指针类型之间进行转换(例如,当通过char *在内存中索引时相当常见), static_cast将生成编译器错误,并且无论如何你将被迫使用reinterpret_cast

In practice I use reinterpret_cast because it's more descriptive of the intent of the cast operation. 在实践中我使用reinterpret_cast,因为它更能描述强制转换操作的意图。 You could certainly make a case for a different operator to designate pointer reinterprets only (which guaranteed the same address returned), but there isn't one in the standard. 您当然可以为不同的运算符设置一个仅指定指针重新解释的情况(保证返回相同的地址),但标准中没有一个。

You likely obtained that void* with implicit conversion, so you should use static_cast because it is closest to the implicit conversion.您可能通过隐式转换获得了void* ,因此您应该使用static_cast ,因为它最接近隐式转换。

Casting to and from void* using static_cast and using reinterpret_cast is identical.使用static_cast和使用reinterpret_cast来回转换void*是相同的。 See the answer at the link .请参阅链接中的答案。 But usually static_cast is preferred because it is more narrow and in general (but not in this specific case) more safe conversion.但通常static_cast是首选,因为它更窄并且通常(但不是在这种特定情况下)更安全的转换。

I suggest using the weakest possible cast always. 我建议总是使用最弱的演员。

reinterpret_cast may be used to cast a pointer to a float . reinterpret_cast可用于将指针强制转换为float The more structure-breaking the cast is, the more attention using it requires. 演员阵容的结构越多,使用它就越需要关注。

In case of char* , I'd use c-style cast, until we have some reinterpret_pointer_cast , because it's weaker and nothing else is sufficient. char*情况下,我会使用c风格的强制转换,直到我们有一些reinterpret_pointer_cast ,因为它更弱,没有其他任何东西就足够了。

Use static_cast for this.为此使用static_cast Only in the rarest of rare cases when there is no other way use reinterpret_cast .仅在极少数情况下没有其他方法时使用reinterpret_cast

There's confusion about implementation defined mappings.关于实现定义的映射存在混淆。 That is about mappings .那是关于映射的。 The implementation can internally map however it likes, but it must make other guarantees otherwise.实现可以按照自己喜欢的方式进行内部映射,但它必须以其他方式做出其他保证。 A result of reinterpret_cast can't simply arbitrarily point to what the implementation would otherwise consider some other object's location -- though the outward representation may differ. reinterpret_cast 的结果不能简单地任意指向实现将考虑其他对象位置的内容——尽管外部表示可能不同。 (Though converting to integer and back will have original value, in specific circumstances, outlined). (虽然转换为整数并返回将具有原始值,但在特定情况下,会进行概述)。 Fundamentally, it's irrelevant whether the implementation's reinterpreted cast returns the same "memory location";从根本上说,实现的重新解释的转换是否返回相同的“内存位置”是无关紧要的; whatever it returns is mapped to the same "value" .它返回的任何内容都映射到相同的“值” (Incidentally, The core guidelines explicitly answer a case where using reinterpret_cast (char*/unsigned char*/std::byte*) to view raw object representation is defined behavior.) (顺便说一下, 核心指南明确回答了使用 reinterpret_cast (char*/unsigned char*/std::byte*) 查看原始对象表示是已定义行为的情况。)

Relevant standards rules the void* cast:相关标准规定 void* 投:

static_cast :静态投射

A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T”, where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. “指向 cv1 void 的指针”类型的纯右值可以转换为“指向 cv2 T 的指针”类型的纯右值,其中 T 是一个对象类型,并且 cv2 与 cv1 具有相同的 cv 资格,或者比 cv1 更高的 cv 资格。 If the original pointer value represents the address A of a byte in memory and A does not satisfy the alignment requirement of T, then the resulting pointer value is unspecified.如果原来的指针值表示一个字节在内存中的地址A,A不满足T的对齐要求,那么得到的指针值是未指定的。 Otherwise, if the original pointer value points to an object a, and there is an object b of type T (ignoring cv-qualification) that is pointer-interconvertible (6.8.3) with a, the result is a pointer to b.否则,如果原始指针值指向一个对象 a,并且有一个类型为 T 的对象 b(忽略 cv 限定)与 a 指针可互换(6.8.3),则结果是指向 b 的指针。 Otherwise, the pointer value is unchanged by the conversion.否则,指针值不会因转换而改变。 [Example 3: T* p1 = new T; const T* p2 = static_cast<const T*>(static_cast<void*>(p1)); bool b = p1 == p2; // b will have the value true. [示例 3: T* p1 = new T; const T* p2 = static_cast<const T*>(static_cast<void*>(p1)); bool b = p1 == p2; // b will have the value true. T* p1 = new T; const T* p2 = static_cast<const T*>(static_cast<void*>(p1)); bool b = p1 == p2; // b will have the value true. —end example] ——结束例子]

reintrepret_cast :重新诠释演员表

An object pointer can be explicitly converted to an object pointer of a different type.68 When a prvalue v of object pointer type is converted to the object pointer type “pointer to cv T”, the result is static_cast<cv T*>(static_cast<cv void*>(v))对象指针可以显式转换为不同类型的对象指针。68 当对象指针类型的纯右值 v 转换为对象指针类型“pointer to cv T”时,结果为static_cast<cv T*>(static_cast<cv void*>(v))

The key is the last sentence.关键是最后一句。 For the purposes of this question's void* cast, (and assuming object types meet alignment requirements, cv qualifications, and are safefly-derived pointers):出于这个问题的 void* 演员的目的,(并假设对象类型满足对齐要求、cv 资格,并且是安全派生的指针):

reinterpret_cast T* from void* is equivalent to static_cast T* from void* .来自 void* 的reinterpret_cast T* from void*static_cast T* from void*

But you should definitely, definitely absolutely definitely use static_cast for no other reason that the scary folklore about reinterpret_cast and convolutedness of the ISO standard may lead to get you needlessly harangued by peers.但是你绝对应该绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对使用static_cast没有其他原因,因为关于 reinterpret_cast 的可怕民间传说和 ISO 标准的复杂性可能会导致你被同行不必要地喋喋不休。

https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Ru-pun https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Ru-pun

reinterpret_cast will forcefully convert the void* to the target data type. reinterpret_cast将强制将void*转换为目标数据类型。 It doesn't guarantee any safety and your program might crash as the underlying object could be anything.它不保证任何安全,您的程序可能会崩溃,因为底层对象可能是任何东西。

For ex, you could typecast an myclass* to void* and then use reinterpret_cast to convert it to yourclass* which may have a completely different layout.例如,您可以将myclass*类型转换为void* ,然后使用reinterpret_cast将其转换为可能具有完全不同布局的yourclass*

So its better and recommended to use static_cast所以它更好,推荐使用static_cast

My personal preference is based on code literacy like this: 我个人的偏好是基于这样的代码识字:

void* data = something;
MyClass* foo = reinterpret_cast<MyClass*>(data);
foo->bar();

or 要么

typedef void* hMyClass; //typedef as a handle or reference
hMyClass = something;
const MyClass& foo = static_cast<MyClass&>(*hMyClass);
foo.bar();

They both do the same in the end, but static_cast seems more appropriate in a middle-ware, app enviroment, while reinterpret cast seems more like something you'd see in a lower-level library IMHO. 他们最终都做了同样的事情,但static_cast似乎更适合中间件,应用程序环境,而重新解释演员似乎更像你在较低级别的图书馆恕我直言中看到的东西。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我应该使用它还是static_cast <void*> 然后是static_cast <myType*> 避免重新解释? - should I use it or static_cast<void*> then static_cast<myType*> to avoid reinterpret_cast? C++ 我们什么时候应该更喜欢使用两个链接的 static_cast 而不是 reinterpret_cast - C++ When should we prefer to use a two chained static_cast over reinterpret_cast 什么时候应该使用 static_cast、dynamic_cast、const_cast 和 reinterpret_cast? - When should static_cast, dynamic_cast, const_cast, and reinterpret_cast be used? 哪个演员使用; static_cast还是reinterpret_cast? - Which cast to use; static_cast or reinterpret_cast? reinterpret_cast的 <int*> (char *)与static_cast <int*> (的static_cast <void*> (char *)) - 使用哪个? - reinterpret_cast<int*>(char*) vs. static_cast<int*>(static_cast<void*>(char*)) — which to use? 为什么Qt使用reinterpret_cast而不是static_cast for void *? - Why does Qt use reinterpret_cast rather than static_cast for void*? C ++类型转换。 static_cast何时成功并且reinterpret_cast会导致问题? - C++ type casting. When will static_cast succeed and reinterpret_cast will cause an issue? 使用C ++样式转换从Void *转换为TYPE *:static_cast或reinterpret_cast - Cast from Void* to TYPE* using C++ style cast: static_cast or reinterpret_cast void * with static_cast vs intptr_t with reinterpret_cast - void* with static_cast vs intptr_t with reinterpret_cast reinterpret_cast <char *>(p)或static_cast <char *>((void *)p))对于字节指针的区别,哪个更好? - reinterpret_cast<char*>(p) or static_cast<char*>((void*)p)) for bytewise pointer difference, which is better?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM