目录
- C++03的左值和右值
- C++11的左值和右值
- 将亡值
在C++03中就有相关的概念
C++03的左值和右值
通俗的理解:
(1) 能放在等号左边的是lvalue
(2) 只能放在等号右边的是rvalue
(3) lvalue可以作为rvalue使用
对于第三点可以举个例子:
int x ;
x = 6; //x是左值,6是右值
int y ;
y = 6; //y是左值,6是右值
y = x; //x作为右值,所以左值是可以作为右值使用的
C++11对左值和右值做出了更加详细的划分。
C++11的左值和右值
表达值分为泛左值、右值;
泛左值分为左值和将亡值(涉及右值引用)
右值可分为纯右值和将亡值(涉及右值引用)
左值指定了一个函数或者对象(表达式计算得出的结果),它是一个可以取地址的表达式。
也就是说,如果一个函数或者对象可以取地址,那么他就是一个左值。
int lv1{ 42 }; // Object
int main() {int& lv2{ lv1 }; // Lvalue reference to Objectint* lv3{ &lv1 }; // Pointer to Object
}
int& lv4() { return lv1; } // Function returning Lvalue Reference
左值例子:
(1) 解引用表达式p
(2) 字符串字面量"abc"
(3) 前置自增/自减表达式 ++i / --i
(4) 赋值或复合运算符表达式(x=y或m=n等)
纯右值是不和对象相关联的值(字面量)或者其求值结果是字面量或者一个匿名的临时对象.
纯右值例子:
(1) 除字符串字面量以外的字面量,比如 32, ‘a’
(2) 返回非引用类型的函数调用 int f() { return 1;}
(3) 后置自增/自减表达式i++/i–
(4) 算术/逻辑/关系表达式(a+b、a&b、a<<b)(a&&b、a||b、~a)(a==b、a>=b、a<b)
(5) 取地址(&x)
如:
72.0f
a–
x为一个整型变量,&x
左值可以当成右值使用
将亡值
将亡值也指定了一个对象,是一个将纯右值转换为右值引用的表达式:
&&这里不是逻辑与运算符,而是右值引用
int&& rvr1{ 22 }; // 右值引用可以引用纯右值
我们先来看什么是左值引用:
a是个左值,b是a的引用,为左值引用。
int a = 1;
int& b = a;
如果a是个常量22,我们对其引用就会出错:
如下:
int& b{22}; //错!非常量左值引用不可引用纯右值
为了解决这个问题,可以使用const 引用(常量左值引用)引用纯右值:
这样就能保证22(纯右值)不会通过b修改,这样b就相当于是22的别名。
const int& b{22};
当然还有另一种引用纯右值的方法就是右值引用了:
通过右值引用可以使纯右值的生存期增加,例如:
int&& rvr1{ 22 }; // 右值引用可以引用纯右值
int rv2 =++rv1;
原本22在执行完第一个语句就会消亡,但是使用右值引用之后,就可以在后面的语句通过调用右值引用,继续使用这个值了。
总例:
int prv(int x) { return 6 * x; } // pure rvalue int main() {const int& lvr5{ 21 }; // 常量左值引用可引用纯右值int& lvr6{ 22 }; // 错!非常量左值引用不可引用纯右值int&& rvr1{ 22 }; // 右值引用可以引用纯右值int& lvr7{ prv(2) }; // 错!非常量左值引用不可引用纯右值int&& rvr2{ prv(2) }; // 右值引用普通函数返回值rvr1 = ++rvr2; // 右值引用做左值使用}