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

Posted

技术标签:

【中文标题】从函数返回的左值引用实际上是右值吗(从调用者的角度来看)?【英文标题】:Is an lvalue reference returned from a function actually an rvalue (from the perspective of the caller)? 【发布时间】:2019-04-15 15:06:24 【问题描述】:

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

class Obj ;

Obj& refToRef(Obj& o) 
    return o;


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

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

【问题讨论】:

【参考方案1】:

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

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

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

如果结果类型是左值引用类型,则函数调用是左值或对函数类型的右值引用,如果结果类型是对对象类型的右值引用,则为 xvalue,以及纯右值否则。

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

【讨论】:

很好的反例来说明大多数价值类别的描述是如何被极度简化的。【参考方案2】:

在考虑表达式的价值性、身份和移动能力时,请记住两个属性。如果表达式具有名称或地址,则表达式具有标识,并且如果在计算表达式后将过期,则表达式是可移动的。

左值 = 有身份且不可移动 Xvalue = 有身份并且 可移动 右值 = 没有身份,可移动

refToRef 通过左值引用返回,因此refToRef(o) 所指的Obj 是一个具有标识(&refToRef(o) 已定义)的对象,并且在计算表达式后仍将存在。 refToRef(o) 因此是一个左值。

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

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

【讨论】:

以上是关于从函数返回的左值引用实际上是右值吗(从调用者的角度来看)?的主要内容,如果未能解决你的问题,请参考以下文章

C++11 中的左值引用和右值引用的区别

C语言 啥叫做左值?右值?

golang os清空返回值

取消引用的指针是有效的左值吗?

什么是右值引用,跟左值又有什么区别?

如何将右值引用从调用者传递给被调用者