右值引用(rvalue reference),是C++11标准提出的一类数据类型。用于实现移动语义(move semantic)与完美转发(perfect forwarding)。但是对于右值引用的理解,自己常常把握不好,现将目前阶段的理解记录下来。有不对的地方欢迎指正。
右值引用的定义
关于“右值引用”的定义,c++ primer(第五版,下同)给了一句废话。。。
所谓右值引用就是必须绑定到右值的引用
然后所谓右值’返回非引用类型的函数,连同算术、下标、解引用和前置递增/递减运算符,都生成右值’
也就是书里所说的将要销毁的对象
个人理解为没有具体变量名的值,一般在一句代码分号结束后就销毁。例如:
int i = 0;
i+1;// 这个就是一个右值。它的值为1,但是没有具体的变量名称,这句代码结束后就被销毁。
右值引用的属性
虽然c++ primer没有给出非常明确的定义,但是说了很多右值的属性和属性便于我们理解
毕竟右值这东西也不是三言两语就能说明白的嘛
右值只能绑定到一个将要销毁的对象。因此,我们可以自由地将一个右值引用的资源”移动”到另一个对象中。
因为右值即将销毁,但是我们定义一个右值引用后,就可以通过这个右值引用访问和修改这个右值,相当于使
这个即将销毁的右值“起死回生”,延长了其生命周期:
struct A{
A(){
cout << "A() "<<endl;
}
~A(){
cout << "~A()" << endl;
}
int i = 0;
};
int main(int argc, char *argv[]){
// 此处注释打开前,A的析构输出会在"end main func"这句之前
/*A&& rA =*/ A();
cout<< "end main func" <<endl;
return 0;
}
类似任何引用,一个右值引用也不过是某个对象的另一个名字而已。
是的,右值引用是一个别名,但是下面这个就不好理解了:
int &&rr1 = 42; // 正确: 字面值常量是右值
int &&rr2 = rr1; // 错误:表达式rr1是左值!
c++ primer对此的解释是:rr1变量名看做是一个没有运算符号的表达式
, 变量表达式都是左值
!!!
最后就很好理解下面这些例子了:
int i = 42;
int &r = i; // 正确: r引用i
int &&rr = i; // 错误: i是变量,变量表达式是左值
int &r2 = i * 42; // 错误:i*42是一个右值
const int &r3 = i * 42; // 正确:const引用可以绑定到一个右值上
int &&rr2 = i * 42; // 正确:右值引用
int &&rr3 = r3; // 错误:r3是变量,变量表达式是左值
const引用和右值引用
const引用和右值引用都可以引用右值,但是const引用只有读权限,右值引用对可以右值有读写(“窃取”资源)权限
一般定义右值引用都是为了修改被引用对象的资源,移动到新的新的对象上去,从而避免浪费,因为右值都是将要被销毁的值
。
所以常量右值引用const X&&
较少用到。