面试官:右值是什么
我:除了左值就是右值?(不确定的语气)
面试官:今天的面试就到这里吧
右值是什么
C/C++代码由标识符(变量、函数、类等的名称)、语句(表达程序中的命令或操作)、表达式(操作数和运算符组成的组合,比如一个常数)组成。
而表达式求职的结果有两个属性:类型(比如int、string、引用)、值类别(左值、右值)
表达式的值类别有两个特征:
-
具名(identity):可以确定表达式是否与另一表达式指代同一实体,例如通过比较它们所标识的对象或函数的(直接或间接获得的)地址。
-
可被移动:移动构造函数、移动赋值运算符或实现了移动语义的其他函数重载能够绑定于这个表达式。
C++11开始,表达式的值分为左值(lvalue, left value)
、将亡值(xvalue, expiring value)
、纯右值(prvalue, pure ravlue)
以及两种混合类别泛左值(glvalue, generalized lvalue)
和右值(rvalue, right value)
五种。
左值 (lvalue):
-
具名且不可被移动的表达式,代表一个持久的对象。可以通过取地址符(
&
)获取其地址。
将亡值 (xvalue):(通过右值引用来续命)
-
具名且可被移动的表达式,表示即将被销毁的对象。可以绑定到移动构造函数或移动赋值运算符。
纯右值 (prvalue):(C++11之前的右值,字面量、非引用的返回值、一些表达式结果,可能在寄存器或者栈内存里)
-
不具名且可被移动的表达式,通常是临时对象或字面量。不能取地址。
泛左值 (glvalue):
-
具名表达式的总称,包括左值和将亡值(xvalue)。
右值 (rvalue):
-
可被移动的表达式的总称,包括纯右值和将亡值(xvalue)。
前置自增(减)是左值,后置自增(减)是纯右值
算术表达式是纯右值
解引用是左值,取地址是纯右值
字符串字面值是左值
可移动是通过移动堆上的指针 和 在栈上预先分配内存实现的
在栈上预先分配内存实现:
A&& ref = createA(); // 绑定将亡值到右值引用
00AF17F2 lea eax,[ebp-32Ch]
00AF17F8 push eax
00AF17F9 call createA (0AF13A2h)
00AF17FE add esp,4
00AF1801 lea ecx,[ebp-32Ch]
00AF1807 mov dword ptr [ref],ecx