C++中fun(T t)与fun(T&& t)模板参数推导类型差异机制问询
嘿,这个问题问到点子上了!正好能把模板参数推导里两个最常用的规则给讲明白,咱们结合你给的代码来拆解:
template <typename T> void fun1(T t) {} template <typename T> void fun2(T && t) {} int i = 1; fun1(i); // 推导得到的T类型为int fun2(i); // 推导得到的T类型为int &
两种模板的推导规则差异详解
一、值参数模板(fun1)的推导逻辑
fun1的参数是T t,属于值传递的模板参数,推导规则非常直接:
- 不管你传入的是左值、右值,还是带引用的变量,编译器都会直接忽略实参的引用属性,把
T推导成实参的基础值类型。 - 比如你传的是
int类型的左值i,那T就直接是int——因为值参数本质是要创建一个实参的拷贝,所以模板参数只需要匹配实参的基础类型就行,引用在这里不影响推导结果。
二、转发引用模板(fun2)的推导逻辑
fun2的参数是T && t,这是C++11引入的转发引用(也叫万能引用),它的推导规则是专门为完美转发设计的,会根据实参的左/右值属性动态调整:
- 当传入左值(比如你的
i)时,编译器会把T推导成该左值的左值引用类型(也就是int&)。这时候T &&就变成了int& &&,根据C++的引用折叠规则,最终会合并成int&,这样就能绑定到左值上; - 如果传入的是右值(比如
fun2(1)),T会被推导成基础值类型int,此时T &&就是int&&,也就是标准的右值引用,能绑定到临时对象上。
核心差异总结
fun1的推导是“去引用化”的:只看实参的基础类型,不管它是左值还是右值、带不带引用;fun2的推导是“保留值类别”的:会根据实参的左/右值属性,把T推导成对应的引用或值类型,目的是完整保留实参的属性,方便后续做完美转发。
另外你提到这个问题不是重复问题,这点完全没问题——之前的问题只单独讲了转发引用的规则,而咱们这里是直接对比了值参数和转发引用两种模板的推导逻辑,针对性更强。
内容的提问来源于stack exchange,提问作者expoter
相关产品推荐
相关产品推荐

