Effective C++代码中为何用reinterpret_cast?能否替换为static_cast?
咱们先把代码整理得更清晰,再一步步拆解你的问题:
static const int signature = 0xDEADBEEF; typedef unsigned char Byte; // this code has several flaws —see below void* operator new(std::size_t size) throw(std::bad_alloc) { using namespace std; size_t realSize = size + 2 * sizeof(int); // 额外申请空间存两个签名 void *pMem = malloc(realSize); // 调用malloc拿原始内存 if (!pMem) throw bad_alloc(); // 内存分配失败抛异常 // 在内存首尾写入签名 *(static_cast<int*>(pMem)) = signature; *(reinterpret_cast<int*>(static_cast<Byte*>(pMem)+realSize-sizeof(int))) = signature; // 返回跳过开头签名的内存指针 return static_cast<Byte*>(pMem) + sizeof(int); }
1. 为什么这里要用reinterpret_cast而非static_cast?
先搞清楚两个转换的核心区别,这事就好理解了:
static_cast:管的是逻辑上相关的类型转换——比如数值类型互转(int→double)、void*和对象指针的双向转换、基类/派生类指针的上下转换(后者要谨慎)。它会做基本的类型检查,确保转换符合C++类型系统的逻辑。reinterpret_cast:是二进制层面的“硬转”——完全跳过类型系统的检查,直接把一块内存的二进制值当成另一种类型来用。它只用于极端的底层内存操作场景,比如完全不相关的指针类型之间的转换。
看代码里的这个关键转换:
reinterpret_cast<int*>(static_cast<Byte*>(pMem)+realSize-sizeof(int))
这里的源类型是Byte*(也就是unsigned char*),目标是int*。这俩指针类型完全不搭边——既不是void*和其他指针的关系,也没有继承或逻辑关联。static_cast根本不支持这种非相关指针的转换,编译器会直接报错。而reinterpret_cast就是干这种“粗暴”活的:把Byte*指向的内存地址,直接当成int*的地址来用,不管类型匹配,这正是我们需要的(因为要在内存末尾写入一个int类型的签名)。
2. 能否将四个类型转换全部替换为reinterpret_cast或static_cast?
分两种情况说:
情况一:全部换成reinterpret_cast
语法上是可行的,但非常不推荐:
- 原本的
static_cast<int*>(pMem)和static_cast<Byte*>(pMem),换成reinterpret_cast<int*>(pMem)、reinterpret_cast<Byte*>(pMem)都是合法的——reinterpret_cast支持void*和任何指针类型的转换。 - 但这么做会糟蹋代码的可读性:
static_cast在这里明确表达了“我把无类型的void*转成有类型指针,这是合理安全的操作”,而reinterpret_cast会让读者误以为这里在搞底层hack,反而混淆了代码意图。
情况二:全部换成static_cast
完全行不通:
- 核心卡壳点就是那个
Byte*转int*的转换——如前所述,static_cast不允许非相关指针类型之间的转换,编译器会直接拒绝这个请求。这个位置必须用reinterpret_cast,没有替代方案。
内容的提问来源于stack exchange,提问作者Yulong Ao
相关产品推荐
相关产品推荐

