01 C++强转的区别
1.1 reinterpret_cast
任意类型的指针之间的相互转换
任意引用之间的相互转换
int& ↔ double& ↔ char&
int*↔ double* ↔ char*↔ void*
例:
int*ptr = reinterpret_cast<int*>(&d);例:
int& ref = reinterpret_cast<int&>(a);
指针 ↔ 整数之间的转换
指针 → 整数:uintptr_t / intptr_t
整数 → 指针:同上
整数类型必须是 uintptr_t 或 intptr_t(保证长度相等)
例:
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr); 核心原理:不修改内存内容
只改变对内存的类型解释
按位重新解读 不允许的转换:
值类型之间的转换(用 static_cast)
删除 const(用 const_cast)
1.2 static_cast
数据转换: 一般是基础整数和浮点数之间的相互转换;
编译时数据的类型发生转换,如果存在可能溢出截断,不会发出告警和错误。
运行阶段,会读取源数据内存,由cpu指令进行转换, 可能发生溢出和截断,也不会发出告警和错误。
指针转换: 继承体系的指针转换或者void *和普通指针之间的转换;
具体向抽象转换:子类转换成为基类(向上转换),或者转换成void*(类型擦除), 是安全的;
抽象向具体转换:基类指针转换成为子类指针(向下转换),或者void*转换成为某个类型的指针(类型擦除后恢复);可能存在安全隐患,需要开发人员确保指针指向的内容和目标类型一致。
使用场合:
架构设计与兼容:如工厂函数接口封装、类型擦除(Type Erasure)、兼容 C 风格底层 API,利用 void* 或基类指针抹平类型差异。
极致性能优化:规避动态多态(虚函数表查找、RTTI 运行期检查)带来的性能损耗与内存膨胀(vptr),满足高频执行代码、游戏引擎、AI 推理框架等对零开销(Zero-overhead)的严苛要求。
1.3 dynamic_cast
dynamic_cast 必须在运行阶段借助 RTTI(Run-Time Type Information,运行阶段类型识别)机制现场进行类型校验。
只能用于多态类型(即类中必须包含至少一个虚函数,否则编译报错)。
向上转换: 子类 →基类,完全安全,隐式转换即可,显式使用较少;
向下转换: 基类->子类, 常用于判断基类数据是否是某个子类;
注意如果是指针转换失败,返回nullptr;
如果是引用转换是被,抛出\<typeinfo>的std::bad_cast错误;
1.4 const_cast
移除 const 属性标记
作用对象:指针和引用
主要场景:调用第三方库或 C 语言接口
原因:这些接口设计不规范,入参没有 const 限定
前提:确保原数据确实是可修改的(不是真正的 const 对象)
重要:不能用来修改真正的 const 对象(未定义行为)
统一接口实现逻辑
应用场景:类中 const 和 non-const 版本的接口
做法:让 non-const 版本转发到 const 版本
目的:避免代码重复,保证逻辑一致性
最佳实践:const 版本写真实逻辑,non-const 版本只负责转发
额外注意:
const_cast 是四大强制转换中最危险的
使用前务必确认原数据的真实可修改性
应避免过度使用,优先考虑 mutable 关键字