请考虑以下示例:
#include <iostream>
#include <typeinfo>
int main()
{
int a=9;
std::cout << typeid(a).name() << '\n';
}
g ++ 4.8.1上的输出:i
MSVS 2010上的输出:int
为什么输出是编译器依赖?这背后的原因是什么?为什么它被保留为实现定义?为什么在所有编译器上没有相同的输出? C ++标准是否明确地说明了它?
答案 0 :(得分:6)
因为编译器以不同的方式表示类型,并且不使用相同的内部结构。
G ++字符串是mangled类型名称,返回(而不是解码)工作更少,效率更高。要求编译器对这些字符串进行解码会增加更多工作量。该标准由实施者决定是否要这样做。
如果标准规定了它,那么它还必须指定各种事物,例如是说signed long
还是仅long
以及如何表示依赖于其他类型和常量的复杂模板实例化。标准化这些字符串的好处是非常小,但需要大量的工作。
答案 1 :(得分:2)
是的,C ++标准明确地说明了这一点:
18.7.1 $ 9,10 Class type_info [type.info]
const char* name() const noexcept;
9返回:An 实施定义的ntbs 10备注:消息可能是a 以null结尾的多字节字符串(17.5.2.1.4.2),适用于 转换并显示为wstring(21.3,22.4.1.4)
答案 2 :(得分:1)
C ++标准说:
类type_info描述了由...生成的类型信息 实现。该类的对象有效地存储指向a的指针 类型的名称,以及适合比较两个的编码值 用于相等或整理顺序的类型。名称,编码规则和 类型的整理顺序都是未指定的,可能有所不同 程序之间。
g ++会返回你可以轻松解除的decorated name。
答案 3 :(得分:0)
为了扩展Jonathan Wakely的答案,typeid
的典型用法是
if ( typeid(variable1) == typeid(variable2) )
// same type
但也
if ( typeid(variable1).name() == typeid(variable2).name() )
// same type
正如您所看到的,无需知道确切的实现定义名称。由于您并不真正需要,标准赋予实现自由,以更有效的方式实现它,这是相当不错的。
例如,比较
_ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_
和std::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
:绝对不那么冗长和有效,比较和存储。
答案 4 :(得分:0)
另外,typeid主要用于多态类型,以便在运行时检测多态对象类型:
#include <iostream>
#include <typeinfo>
class B
{
public:
virtual ~B() {}
};
class D1 : public B
{
};
class D2 : public D1
{
};
int main()
{
B* b1 = new D2;
if (typeid(*b1) == typeid(B))
{
std::cout << "*b1 is B\n";
}
if (typeid(*b1) == typeid(D1))
{
std::cout << "*b1 is D1\n";
}
if (typeid(*b1) == typeid(D2))
{
std::cout << "*b1 is D2\n";
}
}
这将打印
* b1是D2
因此它不适用于打印对象类型的名称。