函数模板进行参数传递时,对引用的传递有两个例外规则:
-
当我们将一个左值(如变量 i)传递给函数的右值引用参数,且此右值引用模板类型的参数(如T&&)时,编译器推断模板类型为实参的左值引用类型。
-
如果我们间接的创建一个引用的引用,则这些引用将会形成“折叠”。
- X& &、X& &&和X&& &都折叠成类型X&
- 类型X&& &&折叠成X&&
引用折叠只能应用于间接创建的引用的引用,如类型别名或者模板参数,我们不能直接创建引用的引用。
template<typename T>
void fun(T &&val);//定义fun为模板函数,参数类型为&&
int i=0;
fun(i);//i是左值,实参将会被推断为int&
int &j = i;
fun(j);//传入的参数为int && &,这时将会从、产生引用折叠,的、折叠后传入的参数实际为 int &.
int &&k = 50;
fun(k);//这时传入的参数为 int && &&,将会被折叠为int &&。
案例:
template<typename T>
void fun(T &&val)
{
T t = val;
t = 10;
}
int i = 0;
int &j = i;
fun(j);
cout << i << endl;//输出i为10
总结:如果一个函数参数是指向模板参数类型的右值引用(T&&),则可以传递给他任意类型的实参,如果将一个左值传递给这样的参数,则函数参数被实例化为一个普通的左值引用(T&)。