int &&rri = 42;
int &&rri1 = rri;
rri是一个左值,rri1不能绑定一个左值。
int&& rri1 = static_cast<int&&>(rri);
但是为什么static_cast转换后就可以了呢?static_cast转换后的类型不还是int&&的吗?
int &&rri = 42;
int &&rri1 = rri;
rri是一个左值,rri1不能绑定一个左值。
int&& rri1 = static_cast<int&&>(rri);
但是为什么static_cast转换后就可以了呢?static_cast转换后的类型不还是int&&的吗?
int&& i1 = 42;
//int&& i2 = i1; // error, 无法将左值绑定到右值引用
int& i3 = i1; // ok
int&& i4 = static_cast<int&&>(i1); // ok
第2行代码,编译给出类似于这样的错误信息:"无法将左值绑定到右值引用"。有一条关于右值引用的规则:编译器将命名的右值引用视为左值,未命名的右值引用视为右值。右值引用支持移动语义的实现,允许将资源从一个对象移动到另一个对象,这样可以避免代价高昂的拷贝操作,从而显著地改进程序的性能。一个命名的对象可以在程序的多个地方被引用,通过赋值或参数传递的方式。如果视一个命名的右值引用为右值,那么这个右值引可能在引用它的多个地方被移动或修改,这样必然引入不易察觉的混乱和危险。考虑下面的代码:
#include <string>
using namespace std;
string make_string(const char* s)
{
return string(s);
}
void example()
{
string&& str1 = make_string("ABC");
// str1 是 "ABC"
string str2 = string(str1);
// 调用拷贝构造函数string(const string&),str2 是 "ABC"
string str3 = string(str1);
// 调用拷贝构造函数string(const string&),str3 是 "ABC"
string str4 = string(static_cast<string&&>(str1));
// 调用移动构造函数string(string&&),str4 是 "ABC", str1 现在是空字符串
string str5 = string(static_cast<string&&>(str1));
// 调用移动构造函数string(string&&),str5 是空字符串.
}
在example函数中,编译器将str1视为左值,所以string(str1)调用拷贝构造函数,而不是移动构造函数,str2和str3分别从str1那里拷贝了资源。表达式static_cast<string&&>(str1)将str1转换为右值引用并返回,返回的右值引用是没有名字的,因此string(static_cast<string&&>(str1))调用移动构造函数,str1的资源被移动到了另一个对象,它现在变成了一个空字符串。
有关右值引用的详细内容,请参考:https://docs.microsoft.com/en-us/cpp/cpp/rvalue-reference-declarator-amp-amp