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

关于lvalue和rvalue引用的困惑:为何rvalue引用变量被当作lvalue处理?

左值引用与右值引用的核心疑问

我难以理解左值(lvalue)和右值(rvalue)引用,以下是我的代码示例:

#include <iostream>

// 返回右值
int Add(int x, int y) {
    return x + y;
}
// 返回左值
int & Transform(int &x) {
    x *= x;
    return x;
}

void Print(int &x) {
    std::cout << "Print(int&) L value ref" << std::endl; 
}
void Print(const int &x) {
    std::cout << "Print(const int&) const l value ref" << std::endl;

}
void Print(int &&x) {
    std::cout << "Print(int &&) r value ref" << std::endl;
}
int main() {
    // x是左值
    int x = 10;
    
    // ref是左值引用
    int &ref = x ;
    // Transform返回左值
    int &ref2 = Transform(x) ;
    // 绑定到接受左值引用的函数
    Print(x);

    Print(ref);
    Print(ref2);

    // rv是右值引用
    int &&rv = 8 ;
    
    // Add返回临时对象(右值)
    int &&rv2 = Add(3,5) ;
    // 绑定到接受临时对象的函数,即右值引用重载
    Print(3);
    Print(rv);
    Print(rv2);
    return 0;
}

运行后输出:

Print(int&) L value ref
Print(int&) L value ref
Print(int&) L value ref
Print(int &&) r value ref
Print(int&) L value ref
Print(int&) L value ref

我大致能理解前4条输出,但最后两条中,rv和rv2是右值引用,为何它们会被传递到接受左值引用的Print函数?


核心原因:命名的右值引用本身是左值

这里的关键规则是:所有命名的变量(包括右值引用变量)在表达式中都是左值。

  • 当你写int &&rv = 8;时,rv是一个有名字的右值引用变量,它绑定了临时值8,但一旦这个引用有了名字,它就变成了可以被取地址、被修改的左值——因为你能通过名字反复访问它,它不再是“临时的、只能用一次”的右值。
  • 所以当你调用Print(rv)或Print(rv2)时,编译器会把它们当作左值处理,因此匹配接受左值引用的Print(int&)重载,而不是右值引用的Print(int&&)。

如果想让右值引用变量以右值的身份传递,需要用std::move()将其转换为右值,比如:

Print(std::move(rv));   // 此时会匹配Print(int&&)
Print(std::move(rv2));  // 同理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 02:58:20