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

函数的左值引用与右值引用有何区别?何时选用?

函数左值引用与右值引用的区别及适用场景

自C11起,存在左值引用(lvalue reference)与右值引用(rvalue reference),我了解二者的常规区别。但与int(*fptr)()这类函数指针类似,C也支持函数的左值引用int(&lvalue)()与右值引用int(&&rvalue)(),但二者似乎并无差异。请问它们的区别是什么,应在何时分别选用?

以下代码使用左值引用与右值引用执行相同操作,二者似乎可互换作为函数参数:

#include<cstdio>
int add(int x){return x+1;}
int runLvalue(int(&input)(int),int val){
    return input(val);
}
int runRvalue(int(&&input)(int),int val){
    return input(val);
}
int main()
{
    int(&lval)(int)=add;
    int(&&rval)(int)=add;
    printf("%d %d %d %d %d %d",
        runLvalue(lval,8),
        runRvalue(lval,9),
        runLvalue(rval,0),
        runRvalue(rval,4),
        lval(5),
        rval(1));
    return 1;
}

输出结果为9 10 1 5 6 2,未体现出选用其中一种函数引用的理由。

你的代码里看不出区别,核心原因是函数本身是左值,且C++允许函数左值绑定到函数右值引用,所以无论是传递命名函数引用还是绑定了左值的右值引用,两个重载函数都能匹配成功。但二者在重载决议、模板编程等场景下存在明确区别,具体如下:

一、核心区别

1. 重载决议的匹配优先级

当存在接受函数左值引用和右值引用的重载函数时:

  • 传递**命名函数(左值)**会优先匹配左值引用版本;
  • 用std::move()将函数转换为右值引用后,会匹配右值引用版本。

示例代码:

#include <cstdio>
#include <utility>

void func() {}

void overload(void(&)()) { printf("匹配左值引用重载\n"); }
void overload(void(&&)()) { printf("匹配右值引用重载\n"); }

int main() {
    overload(func);          // 输出:匹配左值引用重载
    overload(std::move(func));// 输出:匹配右值引用重载
    return 0;
}

2. 模板推导与完美转发

在模板中,函数右值引用结合模板参数可实现万能引用(F&&),既能接受函数左值,也能接受函数右值引用,配合std::forward可完美转发函数的原始值类别;而函数左值引用模板只能接受左值。

示例代码:

#include <cstdio>
#include <utility>

void target(int x) { printf("target: %d\n", x); }

template<typename F, typename... Args>
auto forward_func(F&& f, Args&&... args) -> decltype(f(std::forward<Args>(args)...)) {
    return f(std::forward<Args>(args)...);
}

int main() {
    auto& lfunc = target;
    forward_func(lfunc, 10);   // 转发左值函数引用
    forward_func(std::move(target), 20); // 转发右值函数引用
    return 0;
}

3. 语义区分

  • 函数左值引用通常表示要操作一个持久存在的函数,强调引用的稳定性;
  • 函数右值引用可用来标记临时的函数引用,语义上暗示该引用不需要长期持有(虽然函数本身无法被移动,但可用于区分传递意图)。

二、适用场景

  • 当需要限制参数只能是命名的函数左值时,使用函数左值引用;
  • 当需要在重载中区分左值/右值函数引用,或实现函数引用的完美转发时,使用函数右值引用;
  • 模板编程中,万能引用(F&&)是处理函数引用转发的首选方式,能同时兼容左值和右值场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 04:35:20