rtti是c++运行时类型识别机制,依赖typeid和dynamic_cast,因虚表插入类型信息、全局符号生成及运行时比对而影响性能;关闭后需用type_id虚函数、std::variant或手动类型映射替代dynamic_cast。

RTTI 是什么,为什么它会影响性能
RTTI 是 C++ 在运行时识别对象真实类型的机制,核心是 typeid 和 dynamic_cast。它不是免费的:每个启用了 RTTI 的类,编译器会悄悄在虚函数表(vtable)里塞入类型信息指针;链接时还会生成额外的 typeinfo 全局符号;运行时查类型要走虚表跳转、字符串比较或指针比对——这些都可能打断 CPU 流水线,尤其在热路径里反复调用 dynamic_cast 时,性能损耗明显。
怎么关闭 RTTI(GCC/Clang 和 MSVC 的实操差异)
关闭 RTTI 不是“禁用某个函数”,而是让编译器彻底不生成 typeinfo 数据和相关支持代码。一旦关掉,所有 typeid 表达式和 dynamic_cast 都会在编译时报错,std::type_info 也不再可用。
-
GCC / Clang:加编译选项
-fno-rtti;若用 CMake,在target_compile_options中追加,例如target_compile_options(my_target PRIVATE -fno-rtti) -
MSVC:项目属性 → C/C++ → 语言 → “启用运行时类型信息” → 设为
No (/GR-);命令行对应/GR- - 注意:关掉 RTTI 后,
std::bad_cast和std::bad_typeid异常类型仍存在,但不会被抛出——因为根本没机会触发
关掉 RTTI 后 dynamic_cast 怎么替代
不能用 dynamic_cast 并不等于没法做类型判断。常见替代方案取决于你的场景:
- 如果只是想安全向下转型(比如从基类指针转到某个派生类),且继承结构稳定,用虚函数 + 标识字段更轻量:
virtual int type_id() const { return BASE; },子类重写返回唯一值 - 如果需要多态行为分发,优先用访问者模式或 std::variant(C++17 起),避免运行时类型检查
- 若必须保留类似
dynamic_cast的语义(如插件系统中未知类型交互),可手动维护一个类型 ID 映射表,配合static_cast——但得自己保证类型安全,编译器不再兜底 - 注意:
static_cast在关掉 RTTI 后依然可用,但它不做运行时校验,误用会直接导致未定义行为
容易踩的坑:第三方库和模板实例化
关掉 RTTI 后最隐蔽的问题往往来自依赖项:
立即学习“C++免费学习笔记(深入)”;
- 某些 STL 实现(尤其是老版本 libstdc++)在异常处理路径中隐式依赖
type_info,关 RTTI 后可能链接失败或崩溃;libc++ 通常更友好,但也要验证 - Boost、Qt 等大型库默认假设 RTTI 存在;Qt 的
qobject_cast虽不依赖 RTTI,但若你混用了dynamic_cast就会炸 - 模板实例化可能意外触发 RTTI:比如某模板里写了
typeid(T),哪怕你没显式用,只要该特化被实例化就会报错 - 调试时别忘了:GDB/Lldb 在没有 typeinfo 时无法显示完整类型名,
print obj可能只显示class Base而非实际派生类
真正麻烦的从来不是开关本身,而是关掉之后,所有原本由编译器默默承担的类型安全责任,突然变成你代码里一处处需要手工确认的契约。










