C++中万能引用与std::forward的作用和用法

一句话 :万能引用决定"能不能接住"左值和右值,std::forward 决定"怎么原样交出去"------两者是同一套机制的两半。

万能引用

cpp 复制代码
template<class T>
void f(T&& x);            // 万能引用(标准术语:forwarding reference)

int a;
const int b = 0;
f(a);      // T = int&,         x 的类型是 int&
f(1);      // T = int,          x 的类型是 int&&
f(b);      // T = const int&,   x 的类型是 const int&

它成立的条件只有两个:T 是模板参数 ,且 T 由实参推导 。推导结束后靠引用折叠收尾:T = int& 时 int& && 折叠为 int&,于是左值实参绑定到左值引用;T = int 时得到 int&&,右值实参绑定到右值引用。

值类别的信息被完整编码进了 T,这是后续一切的基础。

万能引用的写法

写法 是否万能引用 原因
template<class T> void f(T&&) ✅ 推导 + T&&
template<class... A> void f(A&&...) ✅ 参数包展开同样是推导
auto&& x = expr; ✅ auto 扮演推导参数(泛型 lambda 同理)
void f(const T&&) ❌ const 挡住了推导成引用的可能
void f(std::vector<T>&&) ❌ 形如 X<T>&&,只是普通右值引用
类模板成员 template<class T> class C { void f(T&&); } ❌ T 在类实例化时就已确定,不随调用推导

std::forward

cpp 复制代码
void sink(int&);
void sink(int&&);

template<class T>
void relay(T&& v) {
    sink(v);                  // ❌ v 是具名变量,永远是左值
    sink(std::forward<T>(v)); // ✅ int& 进则 int& 出,int&& 进则 int&& 出
}

std::forward<T>(v) 本质是 static_cast<T&&>(v):T 是 int& 时折叠回左值,是 int 时得到右值。三条注意事项:

  • 必须显式写 <T>,让编译器知道要还原成什么;
  • T 必须来自同一个转发引用的推导,不能手工指定;
  • 一个参数只转发一次,转发后不要再用它。
相关推荐
九英里路3 小时前
protobuf快速上手
网络·c++·中间件·json·谷歌·序列化·protobuf
纪念 2293 小时前
C++ 算法基础 (差分)
开发语言·c++·算法
ShineWinsu8 小时前
对于Qt:QTreeWidget常见属性以及QTreeWidgetItem类的解析
开发语言·c++·qt·gui·客户端·多叉树·qtreewidget
落羽的落羽9 小时前
【C++】C++17的主要特性
linux·服务器·开发语言·c++·算法·机器学习
汉克老师14 小时前
《从C++小白到算法高手:GESP 1—8级成长地图》第一讲:认识GESP——从编程新手到算法探索者
c++·gesp·信息学竞赛·小学生学c++
晴天的雨.99215 小时前
【C++】继承篇
java·开发语言·c++
青少儿编程课堂16 小时前
蓝桥杯青少组图形化 + 全国青少年信息素养大赛 + 电子学会图形化考级:校园大富翁经营闯关解析
c++·python·算法·bfs·信息学竞赛
another heaven16 小时前
【C/C++ 第一次跨越(上):用 C++11/14 停止制造新的旧代码】
c语言·c++·制造
qq_4069810316 小时前
c++ lamda(三)Lambda表达式
java·前端·c++
I_belong_to_jesus1 天前
C++关于分支预测的优化1
开发语言·c++·算法