我对reinterpret_cast和static_cast的适用性有点困惑。根据我所读到的,一般规则是当类型可以在编译时解释时使用静态强制转换,因此是静态这个词。这也是c++编译器内部用于隐式类型转换的类型转换。
reinterpret_cast适用于以下两种情况:
将整数类型转换为指针类型,反之亦然
将一种指针类型转换为另一种。我得到的一般想法是,这是不可移植的,应该避免。
我有点困惑的地方是我需要的一种用法,我从C调用c++, C代码需要保持c++对象,所以基本上它持有一个void*。在void *和Class类型之间应该使用什么类型转换?
我已经看到使用static_cast和reinterpret_cast?虽然从我所读到的似乎静态更好,因为强制转换可以在编译时发生?虽然它说使用reinterpret_cast从一种指针类型转换为另一种?
c++标准保证了以下内容:
指向void*和来自void*的Static_casting指针将保留地址。也就是说,下面的a、b、c都指向同一个地址:
int* a = new int();
void* b = static_cast<void*>(a);
int* c = static_cast<int*>(b);
Reinterpret_cast只保证如果将一个指针强制转换为不同的类型,然后将其重新转换为原始类型,则得到原始值。下面是:
int* a = new int();
void* b = reinterpret_cast<void*>(a);
int* c = reinterpret_cast<int*>(b);
A和c包含相同的值,但b的值未指定。(在实践中,它通常包含与a和c相同的地址,但标准中没有指定,而且在具有更复杂内存系统的机器上可能不是这样。)
对于void*和void*之间的强制转换,应该优先使用static_cast。
下面是Avi Ginsburg程序的一个变体,它清楚地说明了Chris Luengo、flodin和cmdLP提到的reinterpret_cast属性:编译器将指向内存的位置视为新类型的对象:
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
class A
{
public:
int i;
};
class B : public A
{
public:
virtual void f() {}
};
int main()
{
string s;
B b;
b.i = 0;
A* as = static_cast<A*>(&b);
A* ar = reinterpret_cast<A*>(&b);
B* c = reinterpret_cast<B*>(ar);
cout << "as->i = " << hex << setfill('0') << as->i << "\n";
cout << "ar->i = " << ar->i << "\n";
cout << "b.i = " << b.i << "\n";
cout << "c->i = " << c->i << "\n";
cout << "\n";
cout << "&(as->i) = " << &(as->i) << "\n";
cout << "&(ar->i) = " << &(ar->i) << "\n";
cout << "&(b.i) = " << &(b.i) << "\n";
cout << "&(c->i) = " << &(c->i) << "\n";
cout << "\n";
cout << "&b = " << &b << "\n";
cout << "as = " << as << "\n";
cout << "ar = " << ar << "\n";
cout << "c = " << c << "\n";
cout << "Press ENTER to exit.\n";
getline(cin,s);
}
结果是这样的输出:
as->i = 0
ar->i = 50ee64
b.i = 0
c->i = 0
&(as->i) = 00EFF978
&(ar->i) = 00EFF974
&(b.i) = 00EFF978
&(c->i) = 00EFF978
&b = 00EFF974
as = 00EFF978
ar = 00EFF974
c = 00EFF974
Press ENTER to exit.
可以看到,B对象首先作为特定于B的数据构建在内存中,然后是嵌入的A对象。static_cast正确地返回嵌入的A对象的地址,并且由static_cast创建的指针正确地给出data字段的值。由reinterpret_cast生成的指针将b的内存位置视为普通的a对象,因此当指针试图获取数据字段时,它将返回一些特定于b的数据,就像它是该字段的内容一样。
reinterpret_cast的一个用途是将指针转换为无符号整数(当指针和无符号整数大小相同时):
int我;
Unsigned int u = reinterpret_cast< Unsigned int>(&i);