作用
手册解释如链接。
源码
template <typename T>
class remove_reference
{
public:
typedef T type;
};
template<typename T>
class remove_reference<T&>
{
public:
typedef T type;
};
看看remove_reference 做了什么?
他封装了一个普通的模板类,并且typedef T type,主要看第二个,封装了一个引用类型的T&
。
我们使用时remove_reference<decltype(*a)>
,就会被传到第二个实现中。
remove_reference<int &>
,那么typedef int type
,此时type就会变为int,解除引用。
总结:如果模板T被解释为引用类型,就解引用。
反例一:在不考虑解引用的情况下。
代码
#include "head.h"
#define MY namespace my{
#define MYEND }
using namespace std;
MY
template <typename T>
void swap(T&& a,T&& b){ //使用右值引用传参,可以传参右值或者左值。
cout << a << " "<<b<<endl;
T c = a;
a = b;
b = c;
cout << a << " "<<b<<endl;
return ;
}
MYEND
int main(){
int a = 3,b = 4;
my::swap(a,b); //左值作为参数
my::swap(123,234); //右值作为参数
return 0;
}
结果
3 4
4 4 //不是我们想要的,error
123 234
234 123
分析
main函数中调用swap(a,b)
时,模板推到T&& = int&
(左值),即T = int&
.
此时swap函数中就会变成下面的编译结果:
void swap(int& a,int& b){ //使用右值引用传参,可以传参右值或者左值。
cout << a << " "<<b<<endl;
int& c = a; //即c是a的引用
a = b;
b = c;
cout << a << " "<<b<<endl;
return ;
}
此时c是a的引用,进行传递值的时候,直接将b赋值给了a和c。
这就是为什么产生了3,4经过swap函数变成了4,4。
正例:使用解引用
代码
#include "head.h"
#define MY namespace my{
#define MYEND }
using namespace std;
MY
template <typename T>
void swap(T&& a,T&& b){
//typename remove_reference<T>::type c = a;
remove_reference_t<T> c = a; //解引用使用,这里就不是int&c=a;而是int c = a;
cout << a << " "<<b << endl;
c = a;
a = b;
b = c;
cout << a << " "<<b << endl;
return ;
}
MYEND
int main(){
int a = 3,b = 4;
my::swap(a,b);
my::swap(123,234);
return 0;
}
结果
3 4
4 3
123 234
234 123