为什么name()函数返回的字符串是实现定义的

Why strings returned by name() function is implementation defined?

本文关键字:字符串 实现 定义 返回 name 函数 为什么      更新时间:2023-10-16

考虑以下示例:

#include <iostream>
#include <typeinfo>
int main()
{
    int a=9;
    std::cout << typeid(a).name() << 'n';
}

g++ 4.8.1的输出:i

MSVS 2010输出:int

为什么输出依赖于编译器?这背后的原因是什么?为什么它被保留为实现定义?为什么不是在所有编译器上输出相同的结果?c++标准有明确规定吗?

因为编译器表示类型不同,并且不使用相同的内部结构。

g++字符串是修改过的类型名,返回它(而不是修改它)工作量更少,效率更高。要求编译器修改这些字符串会增加更多的工作。标准留给实现者决定他们是否想这样做。

如果标准规定了它,那么它还必须指定各种各样的东西,比如是说signed long还是只说long,以及如何表示依赖于其他类型和常量的复杂模板实例化。标准化这些字符串的好处非常小,但是需要做大量的工作。

是的,c++标准明确规定:

18.7.1$9,10 Class type_info [type.info]

const char* name() const noexcept; 

9返回:a实现定义的"挪威通讯社"星期六报导。
10备注:留言内容可能为a以空结尾的多字节字符串(17.5.2.1.4.2),适用于转换并显示为wstring (21.3, 22.4.1.4)

c++标准规定:

类type_info描述类生成的类型信息实现。类的对象有效地存储指向对象的指针类型的名称,以及适合于比较两者的编码值用于相等或排序顺序的类型。名称、编码规则和类型的排序顺序都未指定,可能有所不同程序之间。

g++返回给您一个您可以轻松调用的装饰性名称。

进一步扩展Jonathan wakeely的回答,typeid的典型用法是

if ( typeid(variable1) == typeid(variable2) )
     // same type

,还

if ( typeid(variable1).name() == typeid(variable2).name() )
    // same type
如您所见,不需要知道实现定义的确切名称。因为你并不是真的需要它,所以标准给了实现以更有效的方式实现它的自由,这是相当好的。

例如,compare_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&) :绝对更少的冗长和高效,比较和存储。

此外,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 Bn";
    }
    if (typeid(*b1) == typeid(D1))
    {
        std::cout << "*b1 is D1n";
    }
    if (typeid(*b1) == typeid(D2))
    {
        std::cout << "*b1 is D2n";
    }
}

打印

*b1 = D2

所以它不是用来打印对象类型名称的