C++返回右值引用类型的函数返回值是左值还是右值?
关于返回右值引用的函数调用表达式的值类别结论
第二个fun()的返回值确实属于右值,更准确的分类是xvalue(将亡值),属于右值大类,你的测试结果完全符合C++标准的值类别判定规则。
核心判定逻辑
你混淆了两个适用场景不同的值类别规则:
- 函数调用表达式的值类别,只和函数的返回类型直接相关,和引用绑定的目标无关
- 当函数返回类型是左值引用
T&时,函数调用表达式fun()是左值,这也是你第一个测试返回true的原因 - 当函数返回类型是右值引用
T&&时,函数调用表达式fun()是xvalue(将亡值),归属于右值大类,不会被判定为左值
这个判定和你return的对象是全局变量、局部变量,还是move转换的结果没有任何关系,只看函数签名的返回类型。
- 当函数返回类型是左值引用
- 你提到的「声明为右值引用的变量本身也是左值」这个规则是正确的,但它仅适用于有名字的右值引用变量,不适用于函数返回的无名右值引用结果。
举个对比例子:
int x = 9; int&& rref_var = std::move(x); // rref_var是有名字的右值引用变量,表达式rref_var是左值 is_lvalue(rref_var); // 返回true int&& fun() { return std::move(x); } // fun()是返回右值引用的函数调用表达式,没有名字,属于xvalue(右值) is_lvalue(fun()); // 返回false
对你的检测工具的补充说明
你写的is_lvalue是基于转发引用的模板推导规则实现的:
- 传入左值实参时,模板参数
T会被推导为左值引用类型,std::is_lvalue_reference<T>判定为true - 传入右值(包括prvalue纯右值、xvalue将亡值)实参时,模板参数
T会被推导为非引用类型,判定结果为false
所以你的测试结果是完全准确的。
注意:不要因为
fun()返回的右值引用绑定到了全局变量x(有确定内存地址、生命周期长),就误认为这个表达式是左值。C++表达式的值类别是编译期静态属性,和表达式底层绑定对象的存储位置、生命周期没有关联。
内容的提问来源于stack exchange,提问作者Adarsh Singh
相关产品推荐
相关产品推荐

