面试题:static_cast与reinterpret_cast在指针转换中的区别。
面试题:既然static_cast也可以用于指针类型的转换,为什么还需要reinterpret_cast?
这个问题,看了网上的很多答案,其实都没有讲清楚,很多都是说下概念,举例也没有针对性。
static_cast适用于很多情况,我们这里就只说指针类型的转换(也不包括多态类型的指针,另外一篇文章有详细的讲解)
static_cast用于指针类型转换的时候,除了多态类型指针外有两种情况:
1:将 void* 转换为其他类型的指针。
2:同一个类型的不同实例之间进行转换。
而reinterpret_cast要做的恰恰是不同类型之间的转换,它允许我们将一个类型的指针转换为另一个类型的指针,即使它们的内部表示可能完全不同。
我们直接看代码:
#include <iostream>
class MyClass
{
public:
virtual ~MyClass() {}
virtual void doSomething() { std::cout << "MyClass::doSomething()" << std::endl; }
};
class AnotherClass
{
public:
void doAnotherThing() { std::cout << "AnotherClass::doAnotherThing()" << std::endl; }
};
int main()
{
// 尝试转换两个不相关的类对象
AnotherClass anotherObj;
MyClass* Ptr = static_cast<MyClass*>(&anotherObj); // 编译错误
delete Ptr; // 释放内存
return 0;
}
有两个类,MyClass和AnotherClass,这两个类是完全不同的类型,这个时候使用static_cast进行转换,编译直接报错。
错误 C2440 “static_cast”: 无法从“AnotherClass *”转换为“MyClass *” 0711
当把static_cast换成reinterpret_cast的时候,代码编译通过,但是在运行的时候发生了崩溃。
// 尝试转换两个不相关的类对象
AnotherClass anotherObj;
//MyClass* Ptr = static_cast<MyClass*>(&anotherObj); // 编译错误
MyClass* Ptr = reinterpret_cast<MyClass*>(&anotherObj);
delete Ptr; // 释放内存
从这个例子可以看出
如果使用static_cast尝试将一个类型的指针直接转换为另一个不相关类型的指针,将会导致编译错误。这说明了static_cast是一种类型安全的转换方式。
换成reinterpret_cast编译通过,说明了reinterpret_cast 提供的是一种类型不安全的转换方式。而在运行时候崩溃,则告诉我们,reinterpret_cast应该谨慎使用,因为它可能会导致未定义行为。
只有在确实需要进行低级别的类型转换时才使用 reinterpret_cast。比如将指针转换为整数再转换回去等操作,reinterpret_cast 将更有用。
#include <iostream>
int main()
{
// 使用 static_cast
int val = 10;
void* voidPtr = (void*)&val;
int* intPtr = static_cast<int*>(voidPtr); // 从 void* 到 int* 的类型安全转换
// 使用 reinterpret_cast
int value = 1024;
void* voidPtr2 = reinterpret_cast<void*>(&value); // 将 int 转换为 void*
int* intPtr2 = reinterpret_cast<int*>(voidPtr2); // 从 void* 转换回 int*
// 这里展示了一个不安全的转换
double* doublePtr = reinterpret_cast<double*>(intPtr2); // 从 int* 到 double* 的不安全转换
std::cout << "intPtr points to: " << *intPtr << std::endl;
std::cout << "intPtr2 points to: " << *intPtr2 << std::endl;
std::cout << "doublePtr points to: " << *doublePtr << std::endl; // 可能导致未定义行为
return 0;
}
所以为什么需要reinterpret_cast?
当需要将一个类型的指针转换为另一个类型的指针时,就需要用到,但是它的使用一定是心理有数的,确保不会出现未定义的行为。