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 小时前
位运算完整学习笔记:按位与(&)+ 异或(^)
开发语言·c++·算法
努力努力再努力wz6 小时前
【C++高阶系列】C++20 协程底层原理:函数为什么能暂停?从状态机到 Task,彻底串起挂起、恢复与协程调度
开发语言·c++·c++20·1024程序员节
划破黑暗的第一缕曙光6 小时前
[C++]:4.模板
c++·template·模板·函数模版·类模版
十五年专注C++开发6 小时前
pybind11:一个跨C++和Python平台的编程库
开发语言·c++·python·pybind11
CodeYp20196 小时前
第11讲:stack 和 queue
开发语言·c++·queue·stack
沫璃染墨7 小时前
《Qt从零入门系列(十五):Qt线程安全与锁机制详解——从QMutex到RAII与读写锁实战》
开发语言·c++·qt·安全·交互·线程·qt6.3
hetao17338377 小时前
2026-10-25 hetao1733837 的刷题记录
c++·算法
fqbqrr8 小时前
2610C++,UI复合技术在窗口中绘画字体图标
c++·ui
见叶之秋8 小时前
【C++】红与黑的边界:红黑树从插入到自检
数据结构·c++·算法·面试