&&会折叠成&
;当传入参数为右值时,&&不折叠照常接收
void Fun(int& x) { cout << "左值引用" << endl; }
void Fun(const int& x) { cout << "const 左值引用" << endl; }
void Fun(int&& x) { cout << "右值引用" << endl; }
void Fun(const int&& x) { cout << "const 右值引用" << endl; }
// 万能引用:既可以接收左值,又可以接收右值
// 实参左值,他就是左值引用(引用折叠)
// 实参右值,他就是右值引用
template<typename T>
void PerfectForward(T&& t)
{
Fun(t);
}
int main()
{
PerfectForward(10); // 右值
int a;
PerfectForward(a);
return 0;
}
根据本篇博客【第四part】中的结论: 右值引用变量的属性 会被编译器识别成 左值
void Fun(int& x) { cout << "左值引用" << endl; }
void Fun(const int& x) { cout << "const 左值引用" << endl; }
void Fun(int&& x) { cout << "右值引用" << endl; }
void Fun(const int&& x) { cout << "const 右值引用" << endl; }
template<typename T>
void PerfectForward(T&& t)
{
// std::forward<T>(t)在传参的过程中保持了t的原生类型属性
// 完美转发,t是左值引用,保持左值属性
// 完美转发,t是右值引用,保持右值属性
Fun(std::forward<T>(t));
}
int main()
{
PerfectForward(10); // 右值
int a;
PerfectForward(a);
return 0;
}
具体情景演示如下所示:
int main()
{
int a;
int& r = a;
int&& rr = move(a);//std::move()函数位于头文件中,该函数名字具有迷惑性,它并不搬移任何东西
//唯一的功能就是将一个左值强制转化为右值引用,然后实现移动语义
cout << &r << endl;
cout << &rr << endl; //我们知道右值不能取地址,不能被修改,而这里都能正常打印
//证明结论:右值引用变量的属性会被编译器识别成左值
return 0;
}