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

发布于 2024-08-13 08:17:01 字数 435 浏览 11 评论 0原文

我需要将包含地址的整型类型转换为实际的指针类型。我可以按如下方式使用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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

稍尽春風 2024-08-20 08:17:01

不同的 C++ 实现以不同的方式实现对 dynamic_cast 的类型检查;如果您想要特定实现的答案,您应该提及您正在使用的实现。一般来说,回答这个问题的唯一方法是参考 ISO 标准 C++。

根据我对标准的阅读,在 void 指针上调用 dynamic_cast 是非法的:

dynamic_cast<T>(v)

“如果 T 是指针类型,则 v 应是指向完整类类型的指针的右值”

(来自 ISO C++ 标准的 5.2.7.2)。 void 不是一个完整的类类型,因此该表达式是非法的。

有趣的是,被转换的类型可以是一个void指针,即

void * foo = dynamic_cast<void *>(some_pointer);

在这种情况下,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:

dynamic_cast<T>(v)

"If T is a pointer type, v shall be an rvalue of a pointer to complete class type"

(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.

void * foo = dynamic_cast<void *>(some_pointer);

In this case, the dynamic_cast always succeeds, and the resultant value is a pointer to the most-derived object pointed to by v.

小耗子 2024-08-20 08:17:01

不,这样做没有什么特别的好处。当你使用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.

殤城〤 2024-08-20 08:17:01

其实并没有什么太大的优势。如果 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.

伴我老 2024-08-20 08:17:01

安全的方法是保留所有活动 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 unaligned MyClass* pointers from your integers.

以歌曲疗慰 2024-08-20 08:17:01
  • 首先,将 int“重新解释”为 void * 是一个坏主意。如果 sizeof(int) 为 4 并且 sizeof(void *) 为 8(64x 系统),则格式错误。

  • 此外,dynamic_cast仅对于多态类的情况有效。

  • First of all "reinterpreting" int to void * is a bad idea. If sizeof(int) is 4 and sizeof(void *) is 8 (64x system) it is ill-formed.

  • Moreover dynamic_cast is valid only for the case of the polymorphic classes.

墨落成白 2024-08-20 08:17:01

选项 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.

野侃 2024-08-20 08:17:01

在 C++ 中处理指针的最安全方法是类型安全地处理它们。这意味着:

  • 永远不要将指针存储在除指针以外的任何东西中
  • 避免 void 指针
  • 永远不要将指针传递给其他进程
  • 如果您打算在线程上使用指针,请考虑使用weak_ptr

这样做的原因是:您计划做的事情是不安全的,可以避免,除非您正在与不安全(遗留?)代码交互。在这种情况下,请考虑 MSalters 的答案,但请注意,这仍然是一个麻烦。

The safest way to handle pointers in C++ is to handle them typesafe. This means:

  • Never store pointers in anything else than a pointer
  • Avoid void pointers
  • Never pass pointers to other processes
  • consider weak_ptr if you plan to use pointers over threads

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.

星星的轨迹 2024-08-20 08:17:01

如果您确定 the_integer 指向一个已知的基类(至少有一个虚拟成员),那么实际上可能有一个优点:知道该对象属于特定的派生类。但是您必须先reinterpret_cast到您的基类,然后执行dynamic_cast

BaseClass* obj = reinterpret_cast<BaseClass*>(the_integer);
MyClass* myObj = dynamic_cast<BaseClass*>(obj);

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 to reinterpret_cast to your base class first and then do the dynamic_cast:

BaseClass* obj = reinterpret_cast<BaseClass*>(the_integer);
MyClass* myObj = dynamic_cast<BaseClass*>(obj);

Using a void* in dynamic_cast is useless and simply wrong. You cannot use dynamic_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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文