C++:安全的方式投整数指针
-
11-09-2019 - |
题
我需要转换的一个组成型,其中包含一个地址,实际指针的类型。我可以用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);
是否有任何优势,在使用第二种方法?
解决方案
类型上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
指向。
其他提示
没有,有没有具体的优势,在这样做。您使用reinterpret_cast
的那一刻,所有的赌注都关闭。它是由你来确保演员是有效的。
实际上没有严重的优势。如果无效*点的东西,是不是一个指向多态对象,你遇到不确定的行为(通常是访问冲突)马上。
在安全的方式是保持所有活MyClass的对象的记录。最好是保持这个纪录在std::set<void*>
,这意味着你可以轻松地添加,删除和测试的元素。
之所以将它们存储为void*
s是,你不要冒险nastyness喜欢从你的整数创建未对齐MyClass*
指针。
首先"诠释"
int
要void *
是个坏主意。如果sizeof(int)
4和sizeof(void *)
8(64系统)它虐待形成的。而且
dynamic_cast
是有效的情况下,多晶型的课程。
选项1是唯一的(半)便携式/有效的选项。
选项2:无效C ++作为dynamic_cast的(如空隙是不允许的)
。目前的实现水平它需要从源类型的类型信息来获得到目标类型。没有办法(或者有可能是没有办法),以获得从空隙运行时源类型信息*所以这不是有效的任一。
的dynamic_cast用于到CAS上下类型层次不从未知类型。
作为一个侧面说明,你或许应该使用void *的,而不是一个整数存储一个无类型指针。有潜力的一个int不是大到足以存储一个指针。
最安全的方式来处理指针在C++是处理他们的类型安全的。这意味着:
- 从来没有存储指在其他任何东西比一个指
- 避免无效的指针
- 从来没有通过的指针为其他进程
- 考虑weak_ptr如果计划使用的指针在线程
为此原因是:什么你打算要做的就是不安全的和可以避免,除非你在与不安全的(传统?) 代码。在这种情况下考虑MSalters'的答案,但要注意,它仍然是一个麻烦。
如果你确实知道the_integer
点到一个已知的基类(即具有至少一个虚拟构件),有可能实际上是一个优势:知道该对象是一个特定的派生类的。但是你不得不reinterpret_cast
到你的基类,然后再做dynamic_cast
:
BaseClass* obj = reinterpret_cast<BaseClass*>(the_integer);
MyClass* myObj = dynamic_cast<BaseClass*>(obj);
在void*
使用dynamic_cast
是无用的,完全错误的。不能使用dynamic_cast
检查是否有在存储一些任意位置的有效对象。
您也应该在非指针类型变量的存储地址时要注意。有结构的sizeof哪里(无效*)!=的sizeof(int)的,例如LP64。