可能重复:
Should I use static_cast or reinterpret_cast when casting a void* to whatever
在这个程序中,我有void *
作为参数,并希望将其强制转换为特定类型。但我不知道使用哪种“铸造符号”。 static_cast
或reinterpret_cast
都有效。哪一个更好?标准C ++推荐哪一个?
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;
}
在这里,是
A* pA = static_cast<A*>(a);
或
A* pA = reinterpret_cast<A*>(a);
更合适吗?
答案 0 :(得分:48)
static_cast
更适合将void*
转换为其他类型的指针。
static_cast
是在两种类型之间进行自然,直观的转换时的选择,不一定保证在运行时工作。例如,您可以使用static_cast
将基类指针转换为派生类指针,这是一种在某些情况下有意义但在运行时才能验证的转换。同样,您可以使用static_cast
从int
转换为char
,这是明确定义的,但在执行时可能会导致精度损失。
reinterpret_cast
是一个转换操作符,用于执行从根本上说不安全或不可移植的转换。例如,您可以使用reinterpret_cast
从void *
转换为int
,如果您的系统恰好有sizeof (void*)
≤sizeof (int)
,这将正常工作。您还可以使用reinterpret_cast
将float*
转换为int*
,反之亦然,这是特定于平台的,因为float
和{{1}的特定表示形式我们不保证彼此有任何共同之处。
简而言之,如果您发现自己正在进行转换,其中转换具有逻辑意义,但可能不一定在运行时成功,请避免使用int
。 reinterpret_cast
是一个很好的选择,如果你有一些预先知道演员阵容将在运行时工作,并与编译器通信“我知道这可能不起作用,但至少它是有道理的,我有一个理由相信它会在运行时正确地做正确的事。“然后,编译器可以检查转换是否在相关类型之间,如果不是这种情况则报告编译时错误。使用static_cast
执行指针转换可以完全绕过编译时安全检查。
在某些情况下,您可能希望使用reinterpret_cast
而不是dynamic_cast
,但这些情况主要涉及类层次结构中的强制转换,并且(很少)直接关注static_cast
至于哪一个更符合规范,既没有被过度提及为“正确使用”(或者至少,我不记得其中一个被这样提到。)但是,我认为规范希望您使用void*
而不是static_cast
。例如,使用C样式转换时,如
reinterpret_cast
尝试的投射操作符的顺序总是尝试在A* ptr = (A*) myVoidPointer;
之前使用static_cast
,这是您想要的行为,因为reinterpret_cast
不能保证是可移植的。
答案 1 :(得分:1)
使用static_cast
。只有极少数情况下,在没有其他办法的情况下才使用reinterpret_cast
。
答案 2 :(得分:0)
您可能通过隐式转化获得了void*
,因此您应该使用static_cast
,因为它最接近隐式转化。
答案 3 :(得分:0)
如果要沿着类层次结构进行转换,请使用dynamic_cast
- 它会检查以确保实际对象与您要转换的类型兼容。
答案 4 :(得分:-1)
都不是。为什么你首先将指针传递给void?在C中它很常见,因为缺少替代方案,但在C ++中,几乎永远没有理由做任何类似的事情。
编辑:@Dan O提高了使用强制转换来最小化生成代码的可能性。对于任何不太了解他所谈论内容的人,请考虑std::vector
之类的内容 - 当您定义(例如)std::vector<A *>
和std::vector<B *>
时,您通常会结束虽然两者都只是存储指针,但每个代码都有完全独立的代码,因此它们可以共享相同的代码。可以通过定义仅容纳void *
s的容器来解决这个问题,并在从容器中检索项目时转换回正确的类型。
首先,这通常是最好的过早优化(并且通常会变成悲观)。尽管如此,有时候它才有意义。但是,当它执行时,您希望将转换限制为一个位置,但是为{-1}}的伪通用容器创建模板化前端:
void *
现在,我们现在有一个演员阵容。是的,要直接回答原始问题,template <class T>
pointer_container {
std::vector <void *> data;
public:
T *operator[](size_t index) { return static_cast<T *>(data[index]); }
};
是适用于此类情况的正确答案。
回到MS-DOS时代(例如)这样的代码相当常见。然而,今天,这种代码风格毫无意义。
现在,OP已经表示他已经坚持使用固定接口,实现它是他的职责。我不知道他的工作地点或与谁合作,而且我还没有看到其他代码可以使用,所以我不能说确定他们是什么“做的设计很差,应该改变。 OTOH,根据我过去的经验,我猜这种情况的概率至少 99%。因此,我坚持原来的答案。发布的答案刚刚说了“static_cast”,没有任何关于避免演员阵容的答案是真正无益的。虽然几乎不可能无法避免演员 ,但只是假设它是合理的错误的反应和错误答案。
我会更进一步:如果关于投射的问题未能提供关于为什么投射是不可避免的证据,那么任何人都应该认为“好”的仅建议是建议消除完全铸造。它可能(在极少数情况下)证明无法避免演员阵容 - 但这绝对是例外,而不是规则。
答案 5 :(得分:-1)
reinterpret_cast
会强制将void*
转换为目标数据类型。它不保证任何安全性,您的程序可能会崩溃,因为底层对象可能是任何东西。
对于前者,您可以将myclass*
类型转换为void*
,然后使用reinterpret_cast
将其转换为可能具有完全不同布局的yourclass*
。
所以更好,建议使用static_cast