[英]C++: Safe way to cast an integer to a pointer
我需要将包含地址的整数类型转换为实际的指针类型。 我可以按如下方式使用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);
使用第二种方法有什么优势吗?
不,这样做没有特定的优势。 当您使用reinterpret_cast
,所有赌注都关闭了。 由您确定转换是否有效。
实际上没有严重的优势。 如果void *指向不是多态对象的指针的对象,则您会立即遇到未定义的行为(通常是访问冲突)。
对dynamic_cast
类型检查由不同的C ++实现以不同的方式实现; 如果您想为特定的实现提供答案,则应提及您正在使用的实现。 通常,回答该问题的唯一方法是参考ISO标准C ++。
根据我对标准的阅读,在void指针上调用dynamic_cast
是非法的:
dynamic_cast<T>(v)
“如果T是指针类型,则v将是完成类类型的指针的右值”
(来自ISO C ++标准的5.2.7.2)。 void
不是完整的类类型,因此该表达式是非法的。
有趣的是,被强制转换为的类型可以是空指针,即
void * foo = dynamic_cast<void *>(some_pointer);
在这种情况下, dynamic_cast
总是成功,并且结果值是v
指向最派生对象的指针。
安全的方法是保留所有活动的MyClass对象的记录。 最好将此记录保存在std::set<void*>
,这意味着您可以轻松地添加,删除和测试元素。
将它们存储为void*
的原因是,您不会像从整数创建未对齐的MyClass*
指针那样冒着麻烦。
首先,将int
“重新解释”为void *
是一个坏主意。 如果sizeof(int)
为4, sizeof(void *)
为8(64x系统),则格式错误。
此外, dynamic_cast
仅对多态类有效。
如果可以肯定地知道the_integer
指向一个已知的基类(具有至少一个虚拟成员),则实际上可能会有一个好处:知道对象是特定的派生类。 但是您必须先将reinterpret_cast
为您的基类,然后再进行dynamic_cast
:
BaseClass* obj = reinterpret_cast<BaseClass*>(the_integer);
MyClass* myObj = dynamic_cast<BaseClass*>(obj);
在dynamic_cast
使用void*
是没有用的,并且完全是错误的。 您不能使用dynamic_cast
来检查内存中任意位置上是否存在有效对象。
在非指针类型变量中存储地址时,也应注意。 有一些体系结构,其中sizeof(void *)!= sizeof(int),例如LP64。
选项1是您唯一的(半)便携式/有效选项。
选项2:作为dynamic_cast无效的C ++(因为不允许void)。
在实现级别,它需要来自源类型的类型信息才能到达目标类型。 无法(或可能无法)从void *获取运行时源类型信息,因此这也是无效的。
Dynamic_Cast用于提升和降低类型层次结构,而不是未知类型。
附带说明一下,您可能应该使用void *而不是整数来存储无类型的指针。 一个int的大小可能不足以存储指针。
在C ++中处理指针的最安全方法是处理类型安全的指针。 这意味着:
原因是:您打算做的事是不安全的,可以避免,除非您与不安全的(旧版)代码交互。 在这种情况下,请考虑MSalters的答案,但请注意,这仍然很麻烦。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.