右值引用用&&符号表示。右值引用主要是绑定到右值上,如:
int &&rv = 100;
看下面函数定义:
void myfunc(int &&tmprv) {
cout << tmprv << endl;
return;
}
int main() {
myfunc(10); // 正确,右值作为实参
int i = 100;
myfunc(i); // 错误,右值引用不能接受左值
}
由此可知,右值引用肯定不能接受左值,现在将myfunc()函数改造成函数模板:
template<typename T>
void myfunc(T&& tmprv) {
cout << tmprv << endl;
return;
}
如果上面的T是int类型,那么函数myfunc()用int实例化后得到的函数似乎和普通的myfun()函数是一样的,但myfunc(i);并没有报错,因此推断T没有推断为int类型。
1. 万能引用
万能引用又称未定义引用,这种引用离不开两种语境:
- 必须是函数模板;
- 必须是发生了模板类型推断并且函数模板形参如T&&;
万能引用的格式如T&&,auto && tmpvalue = ...也是一个万能引用,其它的&&情况都是右值引用。
2. 万能引用资格的剥夺与辨认
剥夺:
const修饰词(前后)会剥夺一个引用成为万能引用的资格,被打回原型成为右值引用。
template<typename T>
void myfunc(const T&& tmprv) { // 有const存在,为右值引用
cout << tmprv << endl;
return;
}
int main() {
int i = 100;
myfunc(i); // fault
}
辨认:
增加mytest类模板定义:
template<typename T>
class mytest{
pubic:
void testfunc(T&& x) {} // 这不是万能引用,是右值引用
}
int main() {
mytest<int> mc;
int i = 100;
mc.testfunc(i); // fault,左值不能绑定在右值引用上
}
为什么testfunc后面的T&&不是万能引用,而是一个右值引用,因为testfunc()成员函数本身并没有涉及类型推断,testfunc()成员函数是类模板mytest的一部分,首先得用以下语句实例化这个类模板的一个具体类:
mytest<int> mc;
实例完这个类之后,mytest<int>类存在了,那么testfunc()成员函数才真正存在,所以testfunc()成员函数存在的时候就已经为:
void testfunc(int&& x) {}
所以testfunc()函数本身没有涉及类型推断,这个x是右值引用。如果增加一个public修饰的成员函数模板:
template<typename T>
class mytestc {
public:
void testfunc(T&& x) {} // 右值引用
template<typename T2>
void testfunc2(T2&& x) {} // 万能引用
};
int main() {
mytestc<int> myoc;
int i = 10;
myoc.testfunc2(i); // 左值可以,右值10也可以
}
标签:右值,int,万能,引用,&&,testfunc From: https://www.cnblogs.com/love-9/p/18106032