## 左值、右值
在C语言中,我们常常会提起左值 `lvalue` 、右值 `rvalue`这样的称呼。一个最为典型的判别方法就是,在赋值表达式中,出现在等号左边的就是 `左值` ,而在等号右边的,则称为 `右值`。如:
```cpp
int a = 1;
int b = 2;
int c = a + b;
```
在这个赋值表达式中,`c` 就是一个左值,而 `a + b` 则是一个右值。
不过 C++ 中还有一个被广泛认同的说法,那就是可以取地址的、有名字的就是左值,反之,不能取地址的、没有名字的就是右值。那么这个加法赋值表达式中,`&c` 是允许的操作,但 `&(a + b)` 这样的操作则不会通过编译。因此 `c` 是一个左值,`(a + b)` 是一个右值。在C++ 11 中可以取地址的、有名字的就是左值,反之,不能取地址的、没有名字的就是右值(将亡值或纯右值)。
相对于左值,右值表示**字面常量、表达式、函数的非引用返回值**等。
### 右值、将亡值
在理解 C++ 11 的右值前,先看看 C++ 98 中右值的概念:C++ 98 中右值是纯右值,纯右值指的是**临时变量值、不跟对象关联的字面量值**。临时变量指的是非引用返回的函数返回值、表达式等,例如函数int func()的返回值,表达式 `a+b`;不跟对象关联的字面量值,例如 `true`,`2`,`”C”` 等。
C++ 11 对 C++ 98 中的右值进行了扩充。在 C++ 11 中右值又分为纯右值(prvalue,Pure Rvalue)和将亡值(xvalue,eXpiring Value)。其中纯右值的概念等同于我们在 C++ 98 标准中右值的概念,指的是临时变量和不跟对象关联的字面量值;将亡值则是 C++ 11 新增的跟右值引用相关的表达式,这样表达式通常是将要被移动的对象(移为他用),比如返回右值引用 `T&&` 的函数返回值、`std::move` 的返回值,或者转换为 `T&&` 的类型转换函数的返回值。
将亡值可以理解为通过“盗取”其他变量内存空间的方式获取到的值。在确保其他变量不再被使用、或即将被销毁时,通过“盗取”的方式可以避免内存空间的释放和分配,能够延长变量值的生命期。
### 左值引用、右值引用
左值引用是对一个左值进行引用的类型,右值引用则是对一个右值进行引用的类型。
左值引用和右值引用都是属于引用类型。无论是声明一个左值引用还是右值引用,<font color="#FF0000">**都必须立即进行初始化**</font> 。而其原因可以理解为是<font color="#FF0000">**引用类型本身自己并不拥有所绑定对象的内存,只是该对象的一个别名**</font> 。
>左值引用是具名变量值的别名,而右值引用则是不具名(匿名)变量的别名。
**左值引用:**
```cpp
int &a = 2; // 左值引用绑定到右值,编译失败, err
int b = 2; // 非常量左值
const int &c = b; // 常量左值引用绑定到非常量左值,编译通过, ok
const int d = 2; // 常量左值
const int &e = c; // 常量左值引用绑定到常量左值,编译通过, ok
const int &b = 2; // 常量左值引用绑定到右值,编程通过, ok
```
`const 类型 &`为 “万能”的引用类型,它可以接受非常量左值、常量左值、右值对其进行初始化。
**右值引用,使用&&表示:**
```cpp
int && r1 = 22;
int x = 5;
int y = 8;
int && r2 = x + y;
T && a = ReturnRvalue();
```
右值值引用通常不能绑定到任何的左值,要想绑定一个左值到右值引用,通常需要 `std::move()`将左值强制转换为右值,例如:
```cpp
int a;
int &&r1 = c; // 编译失败
int &&r2 = std::move(a); // 编译通过
```
C++ 11 中引用类型以及其可以引用的值的类型总结如下:

C++11:右值引用