typeid 中的表达式在运行时被评估两次?

expression in typeid is evaluated twice in runtime?

请注意,typeid 运算符中的表达式如果是具有虚拟成员的类型的左值,将在运行时进行计算。

我有一个琐碎的Baseclass如下

class Base
{
public:
    Base(const std::string &s):sval(s){}
    virtual ~Base()=default; 
private:
    std::string sval;
};

和 return Base 左值的简单函数如下:

Base& ChangeBase(Base &b)
{
    std::cout<<"Called"<<std::endl;
    return b;
}

当我编写以下代码来检查 typeid 运算符时:

int main()
{

    Base b("Dream");
    typeid (ChangeBase(b));
    return 0;
}

我得到以下输出:

Called
Called

说明函数ChangeBase被调用了两次,那是不是意味着typeid中的表达式会在运行时被求值两次(如果需要在运行时求值)?如果是,为什么?

我正在使用 gcc 4.9.3

GCC 首先检查值是否为 null,然后再次对其进行评估,并且仅在此之后调用 typeid。

程序集:https://godbolt.org/g/SoLFYq

    lea     rax, [rbp-64]
    mov     rdi, rax
    call    ChangeBase(Base&)
    test    rax, rax
    je      .L8
    lea     rax, [rbp-64]
    mov     rdi, rax
    call    ChangeBase(Base&)
...
.L8:
    call    __cxa_bad_typeid