【问题标题】:Why is the output of `typeid(T&).name()` given as `T` instead of `T&`?为什么 `typeid(T&).name()` 的输出是 `T` 而不是 `T&`?
【发布时间】:2020-09-19 09:12:28
【问题描述】:

作为主题,您可以查看https://godbolt.org/z/qtjVP6上的相关代码。

为了您的方便,代码贴在下面:

#include<typeinfo>
#include<iostream>

class Widget{};

Widget someWidget;

int main()
{
    Widget&& var1 = Widget{};      // here, “&&” means rvalue reference
    auto&& var2 = var1;              // here, “&&” does not mean rvalue reference

    std::cout << typeid(var2).name() << std::endl;
}

输出:6Widget

echo 6Widget | c++filt -t 说Widget。

如果能在这个问题上得到一些帮助,我将不胜感激。

【问题讨论】:

    标签: c++ c++11 typeinfo


    【解决方案1】:

    每个C++ Reference(强调我的):

    1) 引用表示类型类型的std::type_info 对象。如果 type 是引用类型,则结果引用代表引用类型的std::type_info对象。

    所以对于type = T&amp;,typeid(type) 将给出关于T 的结果(引用已删除)。

    IMO 很容易理解,就所有目的而言,T&amp; 类型的变量在功能上等同于 T 类型之一。

    【讨论】:

    • 如果我理解正确,对于type=T&amp; 或type=T&amp;&amp;,typeid(type) 将给出关于T 的结果。我对吗?如果是这样,又提出了一个问题,我如何通过二进制程序的输出来区分T&amp; 和T&amp;&amp;。
    • @iBug:在typeid(int)中,int是一个type-id,而在int&amp; a; typeid(a)中,a是一个id-expression ?如果您引用 [expr.typeid]p4,您提供的报价仅适用于typeid(type-id) 形式
    【解决方案2】:

    虽然 iBug 给出的answer 在某种程度上是正确的,但它并不真正适用于您的情况。

    让我们看看 C++ 标准对此有何评论。我们可以看到 [expr]p5 说:

    5 如果表达式最初具有类型“对 T 的引用”([dcl.ref],[dcl.init.ref]),则在进行任何进一步分析之前将类型调整为 T。表达式指定引用所表示的对象或函数,表达式是左值还是x值,具体取决于表达式。

    这就是说:

         std::cout << typeid(var2).name() << std::endl;
    

    在进一步计算表达式之前,var2 的类型从Widget&amp; 调整为Widget。 现在更容易理解为什么typeid(var2).name() 返回一个对应于类型Widget 的字符串。


    如果您想深入挖掘,[expr.typeid]p3 说:

    3 当 typeid 应用于多态类类型的 glvalue 以外的表达式时,结果是指 到表示表达式的静态类型的 std::type_info 对象。左值到右值(4.1),数组到指针 (4.2) 和函数到指针 (4.3) 的转换不适用于表达式。如果类型 表达式是一个类类型,这个类应该是完全定义的。表达式是未计算的操作数 (第 5 条)。

    这基本上意味着typeid(var2) 中的var2 是一个非多态类类型的glvalue,对于这种类型的表达式,类型是它的静态类型。因此类型为Widget。


    详情请见this。

    【讨论】:

    • 感谢您的澄清。您所说的“静态类型”是什么意思(这基本上意味着 typeid(var2) 中的 var2 是非多态类类型的泛左值,用于表达这样的类型,该类型是它的静态类型。)?我能更详细地解释一下吗?如果你能通过给出一些简单的例子来更清楚地说明这一点,我将不胜感激。
    • @sunshilong369 您可以通过以下示例了解静态/动态类型。考虑这段代码class A {}; class B : A {}; A* a1 = new A; A* a2 = new B;,这里*a1 和*a2 的静态类型 是A,但是*a1 的动态类型 是@ 987654339@ 和*a2 是B。简而言之,动态类型通常在继承过程中出现。
    猜你喜欢
    • 2011-09-20
    • 2011-05-12
    • 2020-02-10
    • 1970-01-01
    • 2014-10-28
    • 2017-04-01
    • 2019-04-14
    • 2010-10-14
    • 2019-10-11
    相关资源
    最近更新 更多