万能引用
既能接收左值有能接收右值得引用称为万能引用,万能引用需要与模板一起使用;
——————————————————————————————————————————————非万能引用
例;普通函数中的一个参数要么接收左值类型要么接收右值类型,不能同时接收两种类型。
void func(int&& var){};
int i=100;
func(i);//此时编译报错,只能接收右值
——————————————————————————————————————————————万能引用
template<typename T>
void func(T&& var){};
func(100);
int i=100;
func(i);//传入左值编译器正常通过,这表明T&&左右值都可以接收;
——————————————————————————————————————————————非万能引用
template<typename T>
void func(vector<T>&& VAR)
这里的 vector<T>&& 只是一个右值引用
——————————————————————————————————————————————非万能引用
template<typename T>
class A
{
public;
void func(T&& var){};
}
A obj<int>;
int i=100;
obj.func(i);
以上成员函数不具备类型推导功能,因为在初始化对象时T已经被推导为int型,成员函数形参被推导为int&&右值类型;
成员函数要实现万能引用,需要在成员函数前单独定义template<typename M>类型,切记不要与类模板类型重复;
template<typename T>
class A {
public:
template<typename M>
void func(M&& var) {};
};
——————————————————————————————————————————————万能引用总结
1、万能引用必须和模板一起使用,其他形式无法推断类型
2、万能引用是指(T&&),万能引用不可被包装,vector<T>&& 只是一个右值引用。
3、T&&前最好不要添加关键字,很多关键字会将T&&变成一个右值引用如:const
完美转发
调用模板函数给另一个函数传值时,为了将参数类型保持原本状态传入函数,需要使用完美转发std:forwrad<T>()
完美转发必须与模板一起使用,不能单独使用
template<typename T>
class A {
public:
//成员函数实现完美转发需要单独定义模板
template<typename F,typename T1,typename T2>
void func(F f,T1&& t1,T2&& t2) {
f(forward<T1>(t1), forward<T2>(t2));
};
};
void Bfunc(int&& var1, int&& var2) {};
template<typename F,typename T1,typename T2>
void Afunc(F f,T1&& t1,T2&& t2) {
f(forward<T1>(t1), forward<T2>(t2));
}
void main(){
int i=100;
A obj;
obj.func(Bfunc,i,200);
Afunc(Bfunc.i,200);
}
完美转发,不用担心实参在传入到转发函数时,形参发型类型改变
编译器通过引用折叠实现万能引用,通过引用折叠和万能引用及forward<T>()实现完美转发
可以了解下引用折叠,这里就不做具体介绍了
可以参考:https://blog.youkuaiyun.com/u014351125/article/details/84502427