从函数返回的左值引用实际上是右值(从调用者的角度来看)吗?

Is an lvalue reference returned from a function actually an rvalue (from the perspective of the caller)?

左值引用如何引用从函数返回的左值引用?从调用者的角度来看,从该函数返回的左值引用实际上不是右值吗?例如:

class Obj {};

Obj& refToRef(Obj& o) {
    return o;
}

int main() {
    Obj o;
    Obj& o2 = refToRef(o);
}

o2(左值引用)如何能够引用看似右值的内容?

Isn't the lvalue reference returned from that function actually an rvalue from the perspective of the caller?

不,因为函数调用的结果并不总是右值。

来自 [expr.call]/14(强调我的):

A function call is an lvalue if the result type is an lvalue reference type or an rvalue reference to function type, an xvalue if the result type is an rvalue reference to object type, and a prvalue otherwise.

我很确定这条规则的存在是专门为了避免您的问题所询问的问题。

在考虑表达式的值性、同一性和可移动性时,请记住两个属性。如果表达式具有名称或地址,则它具有身份,并且如果表达式被评估后将过期,则它是可移动的。

  • Lvalue = 有身份且不可移动
  • Xvalue = 具有身份并且 可移动
  • Rvalue = 没有标识且可移动

refToRef returns 通过左值引用,因此 refToRef(o) 引用的 Obj 是一个具有身份的对象(&refToRef(o) 已定义)并且在之后仍然存在该表达式已被评估。 refToRef(o) 因此是一个左值。

此外,请注意不要将类型与价值混淆。如果我添加一个按值 returns 的函数并从中创建一个右值引用,则右值引用将是一个左值。例如

class Obj {};
Obj& refToRef(Obj& o) {
    return o;
}

Obj refToVal(Obj& o) {
    return o;
}
int main() {
    Obj o;
    Obj& o2 = refToRef(o);
    Obj&& o3 = refToVal(o);
}

o3 具有类型 rvalue refernce to Obj,作为表达式是 lvalue.