Possible Duplicate:
Should I use static_cast or reinterpret_cast when casting a void* to whatever
在这个程序中,我有一个void *作为参数,并希望将其强制转换为特定的类型。但我不知道该用哪种"铸造符号"。static_cast或reinterpret_cast都工作。哪一个更好?标准C++推荐哪一种?
1 2 3 4 5 6 7 8 9 10
| typedef struct
{
int a;
}A, *PA;
int foo(void* a) // the real type of a is A*
{
A* pA = static_cast<A*>(a); // or A* pA = reinterpret_cast<A*>(a);?
return pA->a;
} |
这里是
1
| A* pA = static_cast<A*>(a); |
或
1
| A* pA = reinterpret_cast<A*>(a); |
更合适?
static_cast更适合将void*转换为其他类型的指针。
当两种类型之间有一种自然、直观的转换时,static_cast是一种选择类型,这不一定保证在运行时工作。例如,可以使用static_cast将基类指针转换为派生类指针,这种转换在某些情况下是有意义的,但在运行时才能验证。同样,您可以使用static_cast将int转换为char,这是一种定义明确的方法,但在执行时可能会导致精度损失。
另一方面,reinterpret_cast是一个铸造操作员,设计用于进行根本不安全或不可携带的转换。例如,您可以使用reinterpret_cast将void *转换为int,如果您的系统恰好有sizeof (void*)&le;sizeof (int),它将正常工作。您还可以使用reinterpret_cast将float*转换为int*,反之亦然,这是平台特定的,因为float和int的特定表示不能保证彼此有任何共同点。
简而言之,如果您发现自己正在进行一个转换,在这种转换中,强制转换在逻辑上有意义,但在运行时可能不一定成功,请避免使用reinterpret_cast。如果您事先知道强制转换将在运行时运行,并与编译器通信,"我知道这可能不起作用,但至少它是有意义的,并且我有理由相信它在运行时会正确地执行正确的操作",那么static_cast是一个很好的选择。然后,编译器可以检查强制转换是否在相关的如果不是这样,则报告编译时错误。使用reinterpret_cast进行指针转换可以完全绕过编译时安全检查。
在某些情况下,您可能希望使用dynamic_cast而不是static_cast,但这些大多涉及类层次结构中的强制转换,并且(很少)直接涉及void*。
至于规范首选哪一种,也没有过分提到"正确使用"(或者至少我不记得有一种是这样提到的)但是,我认为规范希望您使用static_cast而不是reinterpret_cast。例如,当使用C样式的强制转换时,如
1
| A* ptr = (A*) myVoidPointer; |
试过的铸造操作员的命令总是试图在reinterpret_cast之前使用static_cast,这是您想要的行为,因为reinterpret_cast不能保证是可移植的。
- 澄清:作者这里所说的"EDOCX1"〔0〕是什么意思…不一定保证在运行时工作"是的,你的程序稍后可能崩溃。"如果你从基类型到派生类型的static_cast,它将在运行时"工作"(即你不会得到异常或NULL指针),但如果涉及多个继承,结果可能指向错误的内存位置。(有关详细信息,请参阅此答案。)只有dynamic_cast会执行运行时检查(使用rtti),如果强制转换无效,则会优雅地失败。
为此,请使用static_cast。只有在最罕见的情况下,没有其他方法使用reinterpret_cast。
如果要沿类层次结构强制转换,请使用dynamic_cast—它检查以确保实际对象与要强制转换的类型兼容。
- *不能不使用动态_铸造睾丸甚至有腹部的inheritance。因为参数是无效的*,这是不是在基地的类类型的指针。谢谢你的所有相同。
你很可能通过隐式转换得到了void*,所以你应该使用static_cast,因为它最接近隐式转换。
reinterpret_cast将强制将void*转换为目标数据类型。它不能保证任何安全,并且您的程序可能崩溃,因为底层对象可能是任何东西。
例如,您可以将myclass*类型转换为void*类型,然后使用reinterpret_cast将其转换为yourclass*,这可能具有完全不同的布局。
所以最好还是使用static_cast。
- 静态播放不会阻止这种情况发生。一旦指针退化为一个空*,就可以将其静态转换为任何类型的指针。
两者都不。为什么你要首先传递一个指向虚空的指针?在C中,由于缺少选择,这是相当常见的,但是在C++中,几乎没有理由这样做。
编辑:@dan o提高了使用强制转换最小化生成代码的可能性。对于任何不太了解他所说内容的人来说,考虑一下像std::vector--当你定义(例如)std::vector和std::vector时,你通常会得到一个完全独立的代码,即使两者都只是存储指针,所以它们可以共享相同的代码。通过定义一个只保存void *s的容器,并在从容器中检索项目时将其转换回正确的类型,可以绕过这一点。
首先,这通常是一个过早的优化,充其量(而且往往会被证明是一个对峙)。尽管如此,有时候还是有道理的。但是,当它执行此操作时,您希望将强制转换限制在一个位置,但要创建一个模板化的前端到void *的伪通用容器:
1 2 3 4 5 6
| template <class T>
pointer_container {
std::vector <void *> data;
public:
T *operator[](size_t index) { return static_cast<T *>(data[index]); }
}; |
现在,我们确实有了演员阵容。是的,为了直接回答最初的问题,在这种情况下,使用static_cast是正确的。
在MS-DOS(例如)的时代,这种代码相当常见。然而,今天,这种类型的代码是完全没有意义的。
现在,操作人员已经说他被一个固定的接口卡住了,而实现它是他的工作。我不知道他在哪里工作,也不知道他和谁一起工作,我也没有看到其他代码可以用,所以我不能肯定地说,他们所做的工作设计不好,应该改变。奥思,根据我过去的经验,我想情况至少是99%。因此,我坚持我原来的回答。刚刚贴出的答案说"静态演员表",没有任何关于避免演员表的内容,这些答案真的是无益的。虽然这是几乎不可能的演员真的无法避免,只是假设它的理由是错误的反应和一个坏的答案。
我会更进一步:如果一个关于演员阵容的问题不能提供关于为什么演员阵容不可避免的证据,那么任何人都应该认为"好"的唯一建议就是建议完全消除演员阵容。这可能(在极少数情况下)证明了演员阵容是无法避免的——但这绝对是例外,而不是规则。
- THX为答案。"派"的功能也designed知其他。我的工作就写一个实施。
- 1,因为你说的它自己。"phrase"几乎不"意味着,有几situations当void*也需要这样一个年代,当你使用pthread_create,win32 createthread。
- 从来没有太强的话。一个理由去使用无效* S来保持代码的一代在检查。这一定不应该做的preemptively eventually,但它可能是worthwhile。
- @纳瓦兹:事实上,有几例条纹,require casts并不被证明他们在这个案例的-没有indication腹部,他真正需要的一切所有的。
- @:杰瑞,你认为他应该后的整个项目来证明他的情况吗?他不能让它如此简单的问题,他可以answered容易吗?照常,的问题不是他是否是或不是的先生的情况,而这也是的先生和一个更好的,如果都produce同样的结果。
- @纳瓦兹:当alternatives都是"坏的"和"incorrect",然后neither一"是的先生"或"最好的"。static_cast偷看的可能是现在的alternatives被提出,但这不能使它"是的先生"或"最好的"。
- 杰瑞:argue @我不能与你的时候,没有点。毕竟,你没有被回复到我的问题:你认为他应该后的整个项目来证明他的情况吗?
- 你的问题也没有什么@纳瓦兹:但在秸秆的男人,我们都知道它。在没有做点的状态或甚至imply,posting一整个项目或desirable是必要的。如果你是怎么回答或没有:"你停止爬行beating你妻子呢?"
- 杰瑞:我看到你的argument也是这样:如果我用char代替int,你会说没有indication char是否真的需要,或int会有更好的选择,因为int月亮可以更多的数据比char。这laughable和ridiculous argument!
- @纳瓦兹:你显然不知道足够的关于主体人的手在它intelligently评论到。choosing的datatype也不喜欢choosing铸造-到- casts应该avoided,和几乎总是可以的。没有这样的事也真的无论是char或int。你还没有被answered我的问题:你停止爬行beating你妻子呢?
- 杰瑞:@又一次,你是错过了点。它的坏想法了解到的事情,即使我在刻的我不需要它吗?例如,如果在未来我用pthread_create或CreateThread,void*用途,不会面对问题,铸造也更好,static_cast或reinterepret_cast吗?我不能问的事情,只为仁爱教育专用的吗?我不能问的事情没有explaining为什么我需要这个(AS)是否需要它或不,也itself的问题,事实上,在一个不同的问题)?
- @纳瓦兹:没有。的原因为使用CAST铸造的determines什么应该用。要问我投到没有使用specifying为什么你在用它unlikely到produce的meaningful的结果。
- 杰瑞:@,现在,你会发现一个不同的音。好的。*你的学习。
- 这是一个原因来到了,我用的是sqlite3 API是写在C。它passes空隙的农药callback得到recs。这也是alot起来,在embedded programming在那里你将frequently需要工作与C代码。
- 杰瑞:@和呢,当你在使用的图书馆,你的手和callback无效指针和switching libraries不实用?或者说在图书馆的物体有一个"用户数据"的对象的类型无效*吗?
- michaelgulak @:situations像这样,你在typically要停留在与铸造-但它应该放在usually成template,所以用户代码仍然并不需要应付与它,和代码,并需要包括的铸造并几乎没有什么的,所以它的平凡到verify,它的是的先生。
- 杰瑞:谢谢@ *快速回复。你的意思是,图书馆应该用template,或不知怎的,我应该在对象包装的问题吗?
- michaelgulak @:presumption这里是图书馆,你可以"T modify,所以我说的关于wrapper在那。