typeid 返回 std::type_info 类型的 const 引用,不可直接打印或字符串比较;常见错误是误用 cout

typeid 返回的是类型信息对象,不是字符串
调用 typeid 得到的是 std::type_info 类型的 const 引用,它不支持直接打印或比较字符串。常见错误是写 cout 期望输出类名,结果却是未定义行为或乱码——因为 <code>std::type_info::name() 返回的是编译器特定的内部符号名(如 "St6vectorIiSaIiEE"),不是可读类型名。
- 必须显式调用
.name()才能获取 C 风格字符串指针 -
.name()的返回值生命周期绑定到type_info对象,不能长期保存 - 不同编译器对同一类型的
.name()输出不同(GCC 是 mangled 名,MSVC 可能带空格和修饰)
开启 RTTI 后仍可能拿到不准确的类型名
即使编译时启用了 RTTI(-frtti / /GR),typeid 在多态场景下表现也受对象实际状态影响:
- 对指针或引用使用
typeid(*ptr)才能获得动态类型;typeid(ptr)永远返回指针类型本身(如"PKi") - 若对象是
nullptr,typeid(*ptr)会抛出std::bad_typeid异常 - 对于无虚函数的类,
typeid始终返回静态类型,无法反映继承关系中的实际类型
class Base {};
class Derived : public Base {};
Base b;
Derived d;
Base* p = &d;
cout << typeid(p).name() << endl; // "P4Base"(指针类型)
cout << typeid(*p).name() << endl; // "4Base"(静态类型,因 Base 无虚函数)跨平台获取可读类型名需 demangle
要将 typeid(T).name() 转成类似 "std::vector<int>"</int> 的形式,必须调用 ABI 特定的 demangling 函数:
- GCC/Clang:用
abi::__cxa_demangle(),需手动申请内存并释放 - MSVC:
typeid的.name()默认已 demangle,但含冗余空格和前缀(如"class std::vector<int std::allocator> >"</int>) - 注意:demangle 结果不是标准保证,且
abi::__cxa_demangle可能返回nullptr(如输入非法)
#include <cxxabi.h>
int status;
char* demangled = abi::__cxa_demangle(typeid(std::vector<int>).name(), 0, 0, &status);
if (status == 0) {
cout << demangled << endl; // "std::vector<int, std::allocator<int> >"
free(demangled);
}替代方案:用 constexpr 类型名比 typeid 更可靠
如果目标只是日志、断言或调试输出,typeid 的不可靠性和开销(RTTI 表、虚表查找)让它不如编译期方案:
立即学习“C++免费学习笔记(深入)”;
- C++20 可用
std::source_location::function_name()+ 模板参数推导模拟类型名 - 更通用的做法是用宏 +
__PRETTY_FUNCTION__或__FUNCSIG__提取类型片段(例如 GCC 中__PRETTY_FUNCTION__包含完整模板实参) - 第三方库如 Boost.TypeIndex 提供跨平台、可读、稳定的类型名接口,底层自动处理 demangle 和内存管理
真正需要运行时判断类型时,优先考虑虚函数 + dynamic_cast,而不是依赖 typeid().name() 字符串匹配——后者极易因编译器差异或优化级别变化而失效。











