右值引用是C++11中新增新的引用类型。
右值引用只不过是一种新的 C++ 语法。
基于右值引用,引申出的 2 种 C++ 编程技巧:移动语义和完美转发,难以理解。
引入目的 作用好处
引入右值引用的主要目的是提高程序运行效率。有些对象在复制时需要进行深复制(拷贝),深拷贝往往非常耗时。合理使用右值引用可以避免深复制操作。
右值引用通过减少内存的重复申请、拷贝和释放,有效的提高C++程序的性能。
左值和右值
左值是可寻址的变量;(有名称,能获取其存储地址的实例对象)
右值是不可寻址的字面量,或者表达式求值过程中创建的可寻址的无名临时对象;
无名的临时变量只能在赋值号的右边,而不能出现在赋值号左边。
左值持久性,右值短暂性。
左值的英文简写为“lvalue”,右值的英文简写为“rvalue”。很多人认为它们分别是“left value”、“right value” 的缩写,其实不然。
lvalue 是“loactor value”的缩写,可意为存储在内存中、有明确存储地址(可寻址)的数据,而 rvalue 译为 "read value",指的是那些可以提供数据值的数据(不一定可以寻址,例如存储于寄存器中的数据)。
例如,语句
a = b + c,
其中,a在等号左边,有名,可寻址,且生命周期持久,称为左值;
b+c在等号右边,无名,且在该语句结束后即被销毁从而结束生命周期,被称为右值。
判断某个表达式是左值还是右值,最常用的有以下 2 种方法。
1) 可位于赋值号(=)左侧的表达式就是左值;只能在赋值号右侧的表达式就是右值。举个例子:
int a = 15;
15 = a; //错误,15 不能为左值
其中,变量 a 就是左值,而字面量 15 是右值。左值也可以当做右值使用,例如:
int b = 20; // b 是左值
a = b; // a、b 都是左值,只不过将 b 当做右值使用
2) 有名称的、可以获取到存储地址的表达式为左值;反之是右值。
a 和 b 是变量名,且通过 &a 和 &b 可以获得他们的存储地址,因此 a 和 b 都是左值;而字面量 15、20,它们没有名称,也无法获取其存储地址(字面量通常存储在寄存器中),因此 15、20 都是右值。
int && rr1 =2; //正确,字面值常量是右值
int && rr2 =rr1; //错误,表达式rr1是左值!
注意: 变量 rr1是左值,我们不能将一个右值引用直接赋值给另一个右值引用类型上。
右值引用概念
左值引用
C++98/03 标准中的引用也称为左值引用。
int n= 10;
int &a = n; //正确
int &b = 10; //错误
如上所示,编译器允许我们为 左值 n建立引用,但不可以为右值10建立引用。
const int &b = num;
const int &c = 10;
旧标准可以使用常量左值引用操作右值, 但是无法修改右值。
右值引用
右值引用,可以引用右值,因而称为“右值引用”。
右值引用可以引用无名的临时变量。
右值引用可以修改右值
定义右值引用的格式如下:
类型 && 引用名 = 右值表达式;
例如:
class A{};
A & rl = A(); //错误,无名临时变量 A() 是右值,因此不能初始化左值引用 r1
A && r2 = A(); //正确,因 r2 是右值引用
&&的由来
volatile,pointer(*),reference(&),rvalue reference(&&)
使用
声明即进行初始化
同左值引用一样,右值引用也必须 声明即进行初始化 操作,且只能使用 右值进行初始化,比如:
int num = 10;
//int && a = num; //右值引用不能被初始化为左值
int && a = 10;
右值引用还可以修改右值
和常量左值引用不同的是,右值引用还可以修改右值。例如:
int && a = 10;
a = 50;
cout << a << endl;
程序输出结果为 50。
常量右值引用无用处
C++ 语法上是支持定义常量右值引用的,例如:
const int&& a = 10; //编译器不会报错
但这种定义并无用处。
一方面,右值引用主要用于移动语义和完美转发,其中前者需要有修改右值的权限;
常量右值引用的作用就是引用一个不可修改的右值,这项工作完全可以交给常量左值引用完成。
右值引用是C++11引入的新特性,旨在提高程序效率,减少深拷贝操作。它区分左值和右值,左值持久、可寻址,右值短暂、不可寻址。右值引用可以引用右值,常用于移动语义和完美转发。然而,常量右值引用在实际应用中意义不大。
1万+

被折叠的 条评论
为什么被折叠?



