01 C++强转的区别

1.1 reinterpret_cast

  1. 任意类型的指针之间的相互转换

  2. 任意引用之间的相互转换

    • int& ↔ double& ↔ char&

    • int*↔ double* ↔ char*↔ void*

    • 例:int*ptr = reinterpret_cast<int*>(&d);

    • 例:int& ref = reinterpret_cast<int&>(a);

  3. 指针 ↔ 整数之间的转换

    • 指针 → 整数: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

数据转换: 一般是基础整数和浮点数之间的相互转换;

  1. 编译时数据的类型发生转换,如果存在可能溢出截断,不会发出告警和错误。

  2. 运行阶段,会读取源数据内存,由cpu指令进行转换, 可能发生溢出和截断,也不会发出告警和错误。

指针转换: 继承体系的指针转换或者void *和普通指针之间的转换;

  1. 具体向抽象转换:子类转换成为基类(向上转换),或者转换成void*(类型擦除), 是安全的;

  2. 抽象向具体转换:基类指针转换成为子类指针(向下转换),或者void*转换成为某个类型的指针(类型擦除后恢复);可能存在安全隐患,需要开发人员确保指针指向的内容和目标类型一致。

使用场合:

  1. 架构设计与兼容:如工厂函数接口封装、类型擦除(Type Erasure)、兼容 C 风格底层 API,利用 void* 或基类指针抹平类型差异。

  2. 极致性能优化:规避动态多态(虚函数表查找、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

  1. 移除 const 属性标记

    • 作用对象:指针和引用

    • 主要场景:调用第三方库或 C 语言接口

    • 原因:这些接口设计不规范,入参没有 const 限定

    • 前提:确保原数据确实是可修改的(不是真正的 const 对象)

    • 重要:不能用来修改真正的 const 对象(未定义行为)

  2. 统一接口实现逻辑

    • 应用场景:类中 const 和 non-const 版本的接口

    • 做法:让 non-const 版本转发到 const 版本

    • 目的:避免代码重复,保证逻辑一致性

    • 最佳实践:const 版本写真实逻辑,non-const 版本只负责转发

额外注意:

  • const_cast 是四大强制转换中最危险的

  • 使用前务必确认原数据的真实可修改性

  • 应避免过度使用,优先考虑 mutable 关键字