c++中,不是所有情况下&&都代表一个右值引用,具体的场景体现在模板和自动类型推到中,如果是模板参数,需要指定为&&,如果是自动类型推到需要指定为auto&&,在这两种场景下&&被称为未定义的引用类型,另外还有一点需要额外注意const T&&表示一个右值引用,不是未定义类型。
例1:
template<typename T>
void f(T&& param);
void f1(const T&& param); //const T&&表示一个右值引用
f(10); //10是右值,所有T&&表示右值引用
int x = 10;
f(x); //x是左值,所以T&& 表示左值引用
f1(x); // error, x是左值,const T&&表示一个右值引用
f1(10); // ok, 10是右值
例2:
int x = 520;
int y = 1314;
auto&& v1 = x; // auto&& 表示左值引用
auto&& v2 = 250; //auto&&表示右值引用
由于上述代码中存在T&&或者auto&&这种未定引用类型,当它作为参数时,有可能被一个右值引用初始化,也有可能被一个左值引用初始化,在进行类型推导时右值引用类型(&&)会发生变化,这种变化被称为引用折叠。在C++11中引用折叠的规则如下:
(1)通过右值推导T&&或者auto&& 得到的是一个右值引用类型;
(2)通过非右值(右值引用、左值、左值引用、常量右值引用、常量左值引用)推导T&&或者auto&& 得到的是一个左值引用类型;
总结:就是说只要不是通过右值推导,那就是左值引用;
int&& a1 = 5; //右值引用
auto&& bb = a1; //左值引用
auto&& bb1 = 5; //右值引用
int a2 = 5;
int &a3 = a2; //左值引用
auto&& cc = a3; //左值引用
auto&& cc1 = a2; //左值引用
const int& s1 = 100; //左值引用
const int&& s2 = 100; //右值引用
auto&& dd = s1; //左值引用
auto&& ee = s2; //左值引用
const auto&& x = 5; //const auto&&不是自动推导类型,他表示一个右值引用
#include
using namespace std;
void printValue(int& i)
{
cout << "l-value: " << i << endl;
}
void printValue(int && i)
{
cout << "r-value: " << i << endl;
}
void forward(int&& k)
{
printValue(k); //k作为一个命名对象,这里是左值引用
}
int main()
{
int i = 520;
printValue(i); //左值引用
printValue(1314); //右值引用
forward(250); //左值引用
int&& t = 100;
printValue(t);
return 0;
};