//万能引用 universal reference
#include
#include
#include
using namespace std;
void func(const int& a) { // a的类型: const int &
}
//上面函数改造成模板函数
template
void func1(const T& a){
}
void myfunc(int &&tmprv) { //参数tmprv 是右值引用类型
cout << tmprv << endl;
return;
}
//将上面的 myfunc 函数改造下,
//改造后
//(1) tmprv 既能接受左值,又能接受右值了
//(2) tmprv 的类型是T&&
//
template //模板函数
void myfunc1(T && tmprv) { //&&是属于tmprv 类型的一部分, &&和T类型 没有关系
//T&&或者说tmprv 才是万能引用, 而单独的T 不是万能引用
//如果我传递进来一个整形的左值, tmprv 就应该被推断成int&类型
//如果我传递进来一个整形的右值,tmprv 它就应该被推断成int&&类型
cout << tmprv << endl;
return;
}
template
void funcpd(std::vector&& param) { //右值引用。 非万能引用
}
template //模板函数
void myfunc2(const T && tmprv) {
cout << tmprv << endl;
return;
}
template //模板类
class myTestc {
public:
void testfunc(T&& x) { //这个x是个右值引用,不是万能引用, 因为在实例化后变成如: testfunc(int&& x) ,非testfunc(T&& x)
} //T
template
void testfunc1(T2&& x){ //这是万能引用
}
};
int main(int argc, const char * argv[]) {
//一: 类型区别基本概念
func1(10); //这里调用模板函数,T的类型是“int”, a的类型是“const int &” ;
//(1) 调用函数模板时给的参数 10 会对T的类型产生影响。
//(2) a的类型会对T的类型产生影响
//下面的万能引用就说明了 a的类型会对T的类型产生影响
//二: universal reference / 万能引用 / 未定义引用 基本认识
//&& 表示右值引用。如下:
int && rv = 100;
myfunc(10); // ok
int i = 100;
//myfunc(i); //错误 右值引用不能接收(绑定)左值。无法将参数 i 从“int”转换为“int&&”
myfunc1(i); //正确
//万能引用语境:
//a). 必须是函数模板
//b). 必须是发生了模板类型推断并且函数模板参数的样式是:T&& (auto也存在万能引用的概念)
//T&& : 就是万能引用
//万能引用和右值引用的区别:
//a). 右值引用得传递右值,否则编译器报错。
//b). 万能引用作函数形参时,我们可以传递给它左值,也可以传递给它右值。
//如果我们传递进去了左值,那么这个万能引用就变成了左值引用。
//如果我们传递进去了右值,那么这个万能引用就变成了右值引用。
//判断题:
//(1). void func(int &¶m); //右值引用,因为没模板
//(2). template void func(T&& tmpvalue) {}; // 万能引用
//(3). template void funcpd(std::vector&& param) {}; //右值引用。 非万能引用
std::vector ab = { 1 };
//funcpd(ab); // 错误 因为是右值引用 不能接收左值
funcpd(std::move(ab)); //正确 std::move() 把左值转换为右值
//三: 万能引用资格的剥夺与辨认
//(1) 剥夺 : const 修饰词会剥夺一个引用成为万能引用的资格。会被打回原型成为右值引用。
myfunc2(10);
// myfunc2(i); // 错误 myfunc2 退化成右值引用, 不能接收左值
//(2) 辨认
myTestc mc;
int b = 100;
//mc.testfunc(b);// 错误 testfunc函数参数y为右值引用 不能接收左值
mc.testfunc(std::move(b));//正确 std::move 把左值转换为右值
mc.testfunc1(b); //万能引用 可以接收左值
system("pause");
return 0;
}