C++ 左值引用和右值引用之间的转换
int retVal(int &&v)
{
cout << "右值引用:";
return v;
}
int retVal(int &v)
{
cout << "左值引用:";
return v;
}
int retVal(const int &v)
{
cout << "const 左值引用:";
return v;
}
int getVal()
{
return 999;
}
// 主函数
int main()
{
int a = 100;
int &b = a;
cout << retVal(static_cast<int &&>(a)) << endl;
cout << retVal(static_cast<int &&>(b)) << endl;
cout << retVal(110) << endl;
system("pause");
return EXIT_SUCCESS;
}
输出:
右值引用:100
右值引用:100
右值引用:110
请按任意键继续. . .
可见,上面三个输出,都是精准匹配到的是int retVal(int &&v)
函数。另外左值或左值引用可以通过static_cast<int &&>()
强转成右值类型(这个是 std::move 的基础?);反过来右值不能通过static_cast<int &>()
转成左值引用。如,cout << retVal(static_cast<int&>(getVal())) << endl;
这样子会报错。
下面我们注释掉右值函数:
//int retVal(int &&v)
//{
// cout << "右值引用:";
// return v;
//}
int retVal(int &v)
{
cout << "左值引用:";
return v;
}
int retVal(const int &v)
{
cout << "const 左值引用:";
return v;
}
int getVal()
{
return 999;
}
NS_END
int main()
{
int a = 100;
int &b = a;
cout << retVal(static_cast<int &&>(a)) << endl;
cout << retVal(static_cast<int &&>(b)) << endl;
cout << retVal(110) << endl;
system("pause");
return EXIT_SUCCESS;
}
输出:
const 左值引用:100
const 左值引用:100
const 左值引用:110
请按任意键继续. . .
可见,编译器匹配到的是int retVal(const int &v)
函数。也就是说,int &&
可以转换成const int &v
类型。经测试,不能转换成int &v
类型。
Note: 区分移动和拷贝的重载函数通常有一个版本接受一个
const T&
,而另一个版本接受一个T&&
。 ——《C++ Primer》 P482
所以,一般会重载两个函数,一个是右值引用参数,另一个是 const 左值引用参数。
另外, 函数尾后引用重载版本声明样式如下:
class Foo {
public:
Foo sorted() &&; // 可用于可改变的右值
Foo sorted()const &; // 可用于任何类型的Foo
private:
vector<int> data;
——《C++ Primer》 P484