2009-12-02 136 views
1

我需要将包含地址的整型转换为实际指针类型。我可以使用的reinterpret_cast如下:C++:将整型转换为指针的安全方法

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); 

使用第二种方法有什么好处吗?

+4

第二种方法不是合法的C++,dynamic_cast表达式的类型可能不是void *。 – 2009-12-02 10:46:20

+2

假设整数值最初是一个对象的指针,那么int可能不能保存指针。这就是为什么我们有无效*。如果您正在通过无类型边界投射指针以进行传输,则应将它们转换为void *并返回到原始类型。 – 2009-12-02 10:50:54

+0

他没有特别说'int',类型可能是intptr_t。 – 2009-12-02 10:53:41

回答

2

类型检查dynamic_cast是由不同的C++实现以不同的方式实现;如果你想为你的具体实现提供一个答案,你应该提及你正在使用的实现。一般回答问题的唯一方法是引用ISO标准C++。

通过我的标准的阅读,对空指针调用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

+1

这是因为在'void * foo = dynamic_cast (some_pointer);'之后,你可能会发现'foo!= some_pointer'(这意味着某个\ _pointer指向了一个基础子对象)。 – 2009-12-02 10:49:36

2

不,这样做没有特别的优势。在你使用reinterpret_cast的那一刻,所有投注都关闭。这取决于你确定演员是否有效。

2

其实没有什么重大的优势。如果void *指向的东西不是指向多态对象的指针,则会立即遇到未定义的行为(通常是访问冲突)。

+2

除非你没有。依靠未定义的行为从来不是一个聪明的想法。 – 2009-12-02 10:45:16

1

安全的方法是记录所有活MyClass对象。最好将此记录保存在std::set<void*>之内,这意味着您可以轻松添加,删除和测试元素。

将它们存储为void* s的原因是,您不会冒险像从您的整数中创建未对齐的指针MyClass*这样的冒险。

0
  • 首先是 “重新诠释” intvoid *是一个坏主意。如果sizeof(int)是4并且sizeof(void *)是8(64x系统),则它是不合格的。

  • 此外dynamic_cast仅适用于多态类的情况。

0

如果你肯定知道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。

0

选项1是您唯一的(半)便携式/有效选项。

选项2:与dynamic_cast无效C++(因为void是不允许的)。

在实现级别,它需要来自源类型的类型信息才能到达目标类型。从void *获取运行时源类型信息是没有办法的(或者可能没有办法),所以这也是无效的。

Dynamic_Cast用于对来自未知类型的类型层次结构进行升序和降级。

作为一个附注,你应该使用void *而不是一个整数来存储一个无类型的指针。 int有可能不足以存储指针。

0

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

  • 切勿将指针在别的不是一个指针
  • 避免空指针
  • 从来没有过的指针其他进程
  • 考虑weak_ptr的,如果您计划要使用的线程指针

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