C++:将整数转换为指针的安全方法
我需要将包含地址的整型类型转换为实际的指针类型。我可以按如下方式使用reinterpret_cast:
MyClass *mc1 = reinterpret_cast<MyClass*>(the_integer);
但是,这不会执行任何运行时检查来查看相关地址是否确实包含 MyClass 对象。我想知道首先转换为 void* (使用reinterpret_cast)然后在结果上使用dynamic_cast是否有任何好处。像这样:
void *p = reinterpret_cast<void*>(the_integer);
MyClass *mc1 = dynamic_cast<MyClass*>(p);
assert(mc1 != NULL);
使用第二种方法有什么好处吗?
I need to convert an integral type which contains an address to the actual pointer type. I could use reinterpret_cast as follows:
MyClass *mc1 = reinterpret_cast<MyClass*>(the_integer);
However, this does not perform any run-time checks to see if the address in question actually holds a MyClass object. I want to know if there is any benefit in first converting to a void* (using reinterpret_cast) and then using dynamic_cast on the result. Like this:
void *p = reinterpret_cast<void*>(the_integer);
MyClass *mc1 = dynamic_cast<MyClass*>(p);
assert(mc1 != NULL);
Is there any advantage in using the second method?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
不同的 C++ 实现以不同的方式实现对
dynamic_cast
的类型检查;如果您想要特定实现的答案,您应该提及您正在使用的实现。一般来说,回答这个问题的唯一方法是参考 ISO 标准 C++。根据我对标准的阅读,在 void 指针上调用
dynamic_cast
是非法的:(来自 ISO C++ 标准的 5.2.7.2)。
void
不是一个完整的类类型,因此该表达式是非法的。有趣的是,被转换的类型可以是一个void指针,即
在这种情况下,
dynamic_cast
总是成功,并且结果值是一个指向最-v
指向的派生对象。Type checking on
dynamic_cast
is implemented in different ways by different C++ implementations; if you want an answer for your specific implementation you should mention what implementation you are using. The only way to answer the question in general is to refer to ISO standard C++.By my reading of the standard, calling
dynamic_cast
on a void pointer is illegal:(from 5.2.7.2 of the ISO C++ standard).
void
is not a complete class type, so the expression is illegal.Interestingly, the type being cast to is allowed to be a void pointer, i.e.
In this case, the
dynamic_cast
always succeeds, and the resultant value is a pointer to the most-derived object pointed to byv
.不,这样做没有什么特别的好处。当你使用
reinterpret_cast
的那一刻,一切就都结束了。由您来确保演员阵容有效。No, there's no specific advantage in doing so. The moment you use
reinterpret_cast
, all bets are off. It's up to you to be sure the cast is valid.其实并没有什么太大的优势。如果 void* 指向的不是指向多态对象的指针,您会立即遇到未定义的行为(通常是访问冲突)。
Actually no serious advantage. If the void* points to something that is not a pointer to a polymorphic object you run into undefined behaviour (usually an access violation) immediately.
安全的方法是保留所有活动 MyClass 对象的记录。最好将此记录保存在
std::set
中,这意味着您可以轻松添加、删除和测试元素。将它们存储为
void*
的原因是,您不会冒像从整数创建未对齐的MyClass*
指针这样令人讨厌的风险。The safe way is to keep a record of all live MyClass objects. It's best to keep this record in a
std::set<void*>
, which means you can easily add, remove and test elements.The reason for storing them as
void*
s is that you don't risk nastyness like creating unalignedMyClass*
pointers from your integers.首先,将
int
“重新解释”为void *
是一个坏主意。如果sizeof(int)
为 4 并且sizeof(void *)
为 8(64x 系统),则格式错误。此外,
dynamic_cast
仅对于多态类的情况有效。First of all "reinterpreting"
int
tovoid *
is a bad idea. Ifsizeof(int)
is 4 andsizeof(void *)
is 8 (64x system) it is ill-formed.Moreover
dynamic_cast
is valid only for the case of the polymorphic classes.选项 1 是您唯一(半)可移植/有效的选项。
选项 2:作为dynamic_cast 不是有效的C++(因为不允许使用void)。
在实现级别,它需要来自源类型的类型信息才能到达目标类型。没有办法(或者可能没有办法)从 void* 获取运行时源类型信息,因此这也是无效的。
Dynamic_Cast 用于在类型层次结构中上下转换,而不是来自未知类型。
作为旁注,您可能应该使用 void* 而不是整数来存储无类型指针。 int 可能不够大,无法存储指针。
Option 1 is your only (semi) portable/valid option.
Option 2: is not valid C++ as the dynamic_cast (as void is not allowed).
At an implementation level it requires type information from the source type to get to the destination type. There is no way (or there may be no way) to get the runtime source type information from a void* so this is not valid either.
Dynamic_Cast is used to cas up and down the type hierarchy not from unknown types.
As a side note you should probably be using void* rather than an integer to store an untyped pointer. There is potential for an int not to be large enough to store a pointer.
在 C++ 中处理指针的最安全方法是类型安全地处理它们。这意味着:
这样做的原因是:您计划做的事情是不安全的,可以避免,除非您正在与不安全(遗留?)代码交互。在这种情况下,请考虑 MSalters 的答案,但请注意,这仍然是一个麻烦。
The safest way to handle pointers in C++ is to handle them typesafe. This means:
The reason for this is: what you are planning to do is unsafe and can be avoided unless you're interfacing with unsafe (legacy?) code. In this case consider MSalters' answer, but be aware that it still is a hassle.
如果您确定
the_integer
指向一个已知的基类(至少有一个虚拟成员),那么实际上可能有一个优点:知道该对象属于特定的派生类。但是您必须先reinterpret_cast
到您的基类,然后执行dynamic_cast
:在
dynamic_cast
中使用void*
code> 毫无用处,而且根本就是错误的。您不能使用dynamic_cast
来检查内存中的任意位置是否存在有效对象。在非指针类型变量中存储地址时还应该注意。有些架构的 sizeof(void*) != sizeof(int),例如 LP64。
If you know for sure that
the_integer
points to a known base class (that has at least one virtual member), there might in fact be an advantage: knowing that the object is of a specific derived class. But you’d have toreinterpret_cast
to your base class first and then do thedynamic_cast
:Using a
void*
indynamic_cast
is useless and simply wrong. You cannot usedynamic_cast
to check if there’s a valid object at some arbitrary location in memory.You should also pay attention when storing addresses in non-pointer type variables. There are architectures where sizeof(void*) != sizeof(int), e.g. LP64.