You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何返回右值引用的表达式无法初始化非const左值引用?

关于右值引用作为函数返回值的值类别疑惑解答

嘿,这个问题其实戳中了C++里最容易混淆的点之一:引用类型和表达式的值类别完全是两码事!很多人刚接触右值引用时都会在这里绕晕,我来给你拆解清楚。

先直接回答你的两个核心问题

  1. 示例1中的fun()表达式是右值(更准确地说是「亡值xvalue」,属于右值的范畴)
  2. 示例1中的fun()的返回类型确实是右值引用int&&

这两个结论并不矛盾,因为「返回的引用类型」和「函数调用表达式的值类别」是两个独立的概念,我们逐个看你的示例就能明白:


示例1:返回右值引用的函数调用为何是右值?

先看代码:

int &&fun() { return 1; } 
int main() { int &a = fun(); } // 编译报错

C++标准有明确规则:

  • 如果函数返回左值引用T&,那么函数调用表达式是左值
  • 如果函数返回右值引用T&&,那么函数调用表达式是xvalue(亡值)——而亡值属于右值的一种
  • 如果函数返回非引用类型T,函数调用表达式是prvalue(纯右值),也是右值

而左值引用int&只能绑定到左值,不能直接绑定右值(除非是const int&,它可以绑定所有值类别),所以编译器报错“无法用int右值初始化int&”。

示例2:返回左值引用的函数调用是左值

代码:

int & fun(){ int b; return b; } 
int main(){ int & a=fun(); } // 编译通过(仅警告)

这里fun()返回左值引用,所以函数调用表达式是左值,左值引用int&自然可以绑定到左值。当然,返回局部变量的引用是未定义行为,编译器只会给警告,但语法上是允许的。

示例3:decltype保留返回的引用类型

代码:

int &&fun() { return 1; } 
int main() { decltype(fun()) b = 1; } // 编译成功

decltype的规则是:对于函数调用表达式,如果函数返回引用类型,decltype(fun())会直接保留这个引用类型(这里就是int&&),所以你可以用它初始化右值引用变量,这只能证明函数的返回类型是右值引用,和fun()表达式本身的值类别无关。

示例4:具名的右值引用是左值

代码:

int &&a = 1; 
int &b = a; // 编译通过

这里的a是具名的右值引用变量——注意:所有具名的变量(不管是左值引用、右值引用还是普通变量)都是左值!所以a是左值,左值引用int&当然可以绑定到它。这和示例1完全不矛盾,因为示例1中的fun()是函数调用表达式(xvalue,右值),而示例4中的a是具名变量(左值)。


最后总结几个关键规则,帮你理清逻辑

  • 具名引用都是左值:不管是int&还是int&&类型的变量,只要有名字,它就是左值
  • 函数返回值的类型决定表达式的值类别:
    • 返回T& → 函数调用是左值
    • 返回T&& → 函数调用是xvalue(右值)
    • 返回非引用T → 函数调用是prvalue(右值)
  • 左值引用的绑定规则:T&只能绑定左值,const T&可以绑定左值、右值
  • 右值引用的绑定规则:T&&可以绑定右值,也可以通过std::move绑定左值(把左值转成右值)

内容的提问来源于stack exchange,提问作者namasikanam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:02:44