繁体   English   中英

C ++:将整数强制转换为指针的安全方法

[英]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 ++中处理指针的最安全方法是处理类型安全的指针。 这意味着:

  • 切勿将指针存储在指针以外的任何其他位置
  • 避免空指针
  • 永远不要将指针传递给其他进程
  • 如果您打算在线程上使用指针,请考虑weak_ptr

原因是:您打算做的事是不安全的,可以避免,除非您与不安全的(旧版)代码交互。 在这种情况下,请考虑MSalters的答案,但请注意,这仍然很麻烦。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM