static_cast和reinterpret_cast似乎都可以很好地将void*转换为另一个指针类型.是否有充分理由支持其他人?
我明白这reinterpret_cast很危险,我只是这样做来测试它.我有以下代码:
int x = 0;
double y = reinterpret_cast<double>(x);
Run Code Online (Sandbox Code Playgroud)
当我尝试编译程序时,它给我一个错误说
从'float'类型转换为'double'类型无效
这是怎么回事?我认为reinterpret_cast是你可以用来将苹果转换为潜艇的流氓演员,为什么这个简单的演员不会编译?
考虑以下代码(以及VirtualAlloc()返回avoid*的事实):
BYTE* pbNext = reinterpret_cast<BYTE*>(
VirtualAlloc(NULL, cbAlloc, MEM_COMMIT, PAGE_READWRITE));
Run Code Online (Sandbox Code Playgroud)
为什么reinterpret_cast选择而不是static_cast?
我以前认为reinterpret_cast可以用于例如从整数类型(例如DWORD_PTR)转换指针,但是从a转换void*为a BYTE*,是不是static_cast可以?
在这种特殊情况下是否存在任何(微妙的?)差异,或者它们是否只是有效的指针转换?
C++标准是否偏爱这种情况,建议采用一种方式而不是另一种方式?
显然,编译器认为它们是不相关的类型,因此reinterpret_cast是必需的.为什么这是规则?
我的理解是C++ reinterpret_cast和C指针转换只是一个编译时功能,它根本就没有性能成本.
这是真的?
说我想投A*,char*反之亦然,我们有两个选择(我的意思是,我们很多人认为我们有两个选择,因为两者似乎都有效!因此混乱!):
struct A
{
int age;
char name[128];
};
A a;
char *buffer = static_cast<char*>(static_cast<void*>(&a)); //choice 1
char *buffer = reinterpret_cast<char*>(&a); //choice 2
Run Code Online (Sandbox Code Playgroud)
两者都很好.
//convert back
A *pA = static_cast<A*>(static_cast<void*>(buffer)); //choice 1
A *pA = reinterpret_cast<A*>(buffer); //choice 2
Run Code Online (Sandbox Code Playgroud)
即便这样工作正常!
那么,为什么我们reinterpret_cast在C++中有两个链接 static_cast可以完成它的工作呢?
你们中的一些人可能认为这个主题与之前的主题重复,例如本文底部列出的,但事实并非如此.这些主题讨论只在理论上,但他们没有给出甚至一个例子来展示为什么reintepret_cast是真正需要的,而2 static_cast将肯定会失败.我同意,一个static_cast会失败.但两个怎么样?
如果两个链接的语法static_cast看起来很麻烦,那么我们可以编写一个函数模板,使其对程序员更友好:
template<class To, class From>
To any_cast(From v)
{
return static_cast<To>(static_cast<void*>(v));
}
Run Code Online (Sandbox Code Playgroud)
然后我们可以使用它,如:
char *buffer = any_cast<char*>(&a); …Run Code Online (Sandbox Code Playgroud) 我刚刚在Qt中找到了以下代码,我对这里发生的事情感到有些困惑.
特别是对于什么reinterpret_cast<T>(0)呢?
template <class T>
inline T qobject_cast(const QObject *object)
{
// this will cause a compilation error if T is not const
register T ptr = static_cast<T>(object);
Q_UNUSED(ptr);
#if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(QT_NO_QOBJECT_CHECK)
reinterpret_cast<T>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(const_cast<QObject *>(object)));
#endif
return static_cast<T>(const_cast<QObject *>(reinterpret_cast<T>(0)->staticMetaObject.cast(const_cast<QObject *>(object))));
}
Run Code Online (Sandbox Code Playgroud)
有人在乎解释吗?
我正在读一本书而且我发现reinterpret_cast不应该直接使用,而是将其与无效*结合使用static_cast:
T1 * p1=...
void *pv=p1;
T2 * p2= static_cast<T2*>(pv);
Run Code Online (Sandbox Code Playgroud)
代替:
T1 * p1=...
T2 * p2= reinterpret_cast<T2*>(p1);
Run Code Online (Sandbox Code Playgroud)
但是,我找不到解释为什么这比直接演员更好.如果有人能给我一个解释或指出我的答案,我将非常感激.
提前致谢
ps我知道用的是什么reinterpret_cast,但我从未见过以这种方式使用它
我的编译器是最新的VC++ 2013 RC.
void f()
{
int n1 = 0;
int n2 = reinterpret_cast<int>(n1); // error C2440
}
Run Code Online (Sandbox Code Playgroud)
错误C2440:'reinterpret_cast':无法从'int'转换为'int'
为什么在这种明显的情况下不能使用reinterpret_cast?
是底层位表示一个std::array<T,N> v和T u[N]一样的吗?
换句话说,将N*sizeof(T)字节从一个复制到另一个是否安全?(通过reinterpret_cast或memcpy.)
编辑:
为了澄清,重点是相同的位表示和reinterpret_cast.
例如,假设我将这两个类放在一些简单的可复制类型上T,对于某些类N:
struct VecNew {
std::array<T,N> v;
};
struct VecOld {
T v[N];
};
Run Code Online (Sandbox Code Playgroud)
还有遗留功能
T foo(const VecOld& x);
Run Code Online (Sandbox Code Playgroud)
如果表示相同,则此调用是安全的并且避免复制:
VecNew x;
foo(reinterpret_cast<const VecOld&>(x));
Run Code Online (Sandbox Code Playgroud)