- 1.引入
- 2.左值与右值
- 2.1.左值与右值的概念
- 2.2.C++中各种左值和右值的概念
- 2.3.理解左值和右值
- 2.4.左值与右值的转换
- 2.5.再论decltype
注意左值和右值的概念是相对于赋值表达式的=来说的,对于一个对象或者数值,不能说它是左值还是右值,就没有这种说法。而是应该把这个对象或者数值带入到复制表达式中,说它在这个表达式中是左值还是右值。
int x; // 这里不能说它是左值还是右值 x = 3; // 在这个表达式中,x是左值,3是右值2.2.C++中各种左值和右值的概念
首先明确,下面所说的求值的概念并不是通常所说的把变量的值是多少拿出来,而更像是确定某个量的本质是什么;比如对泛左值求值,得到的是它所关联的那块内存;对纯右值求值,得到的可能就是某个运算符的操作数。
- glvalue(泛左值):首先它是一个表达式,它的求值结果是一个对象、位域(对象在内存中的哪个位)或者函数。比如对于语句x = 3,首先对x求值,再对3求值,然后再赋值。这里对x求值实际上不是真的对x求值看它里面存储的数值是多少,本质上是确定x所关联的内存。
- prvalue(纯右值):和泛左值相对应,首先它也是一个表达式,它的求值结果是一下两个之一:
- 它作为某个运算符的操作数,比如x=3中=是一个运算符,其中的3只能被当做操作数,因为不能写成3=x,也就是它不能作为这个运算符的赋值对象。再比如3+2,其中3和2都是操作数。
- 它用来初始化某个对象或者位域。比如语句int x = 3,这里=并不是一个赋值运算符,而是代表拷贝初始化。所以这里的3就是用来初始化某个对象,而没有对应具体的标识,因为没有对应的内存来显式的表示它。
- xvalue(亡值):首先它是一个泛左值,然后它代表其资源能够被重新使用的对象或者位域。为了理解将亡值,这里需要先介绍右值引用的概念:
#include2.3.理解左值和右值#include // 注意这里的两个&&代表右值引用,后面会继续讲解右值引用的操作 void fun(std::vector && par) { // 在这里面就可以对x的资源进行重复利用,因为x是将亡值, // 外面不会对它进行操作了 } int main() { std::vector x; // 使用std::move把x构造成一个将亡值,现在的x只是一个泛左值(因为它绑定了一块内存) fun(std::move(x)); // 上面把x转成将亡值的目的就是后面不会再对x的资源进行任何的处理, // 因为我们认为x是一个将亡值,是即将死亡的,所以在这里就会把x资源 // 交出去,后面不会再对x的资源进行处理。这样在fun函数里面就可以 // 任意操作x了 // .... }
-
左值首先是一个泛左值,也就是它是表达一个对象,绑定一块内存的。其次只要它不是一个将亡值,那么他就是一个左值。
而右值则包括两部分, 一种是纯右值,它只能被当做操作符的操作数或者被用来初始化对象。如果它不是纯右值,那么它就是将亡值。 -
理解左值不一定能放在等号左边:
// 首先x绑定了一块内存,所以它是泛左值。其次后面一直可以使用它, // 所以它不是将亡值。因此x是一个左值 const int x = 3; // 但是左值不一定能放在等号左边,因为x是const x = 4; // 错误
- 理解右值也可以放在等号左边:
struct Str {} ;
// 首先Str()这种写法类似匿名对象?得到的是一个纯右值,可以用它来
// 初始化对象。但是它也可以放在等号左边,下面语句的意思,就是用右边的纯右值,初始化左边的匿名对象。
Str() = Str();
2.4.左值与右值的转换
- 左值转换成右值
int x = 3; // x是左值 int y = x; // x是左值,作为右值给y初始化
- 临时具体化
struct Str
{
int x;
};
int main()
{
// 这里单独写Str()类似一个匿名对象,它没有绑定具体哪一块内存,
// 所以它是一个纯右值,一般用于操作数或者对象的初始化。但是这里
// 用.操作符取其中的x,类似于把Str()这个对象具体化了,然后取它其
// 中对应x的内存,所以这里的Str()就要把它视为将亡值,并且是属于
// 泛左值类型的将亡值,这样才能取它其中的x对应的内存。
// 这种就是临时具体化
Str().x
}
2.5.再论decltype
现在重点关注decltype的实参是表达式的情况:
-
表达式的类型是将亡值,则产生T的右值引用:
-
表达式的类型是左值,则产生T的引用:注意下面的代码中,decltype((x))中x必须加(),因为这样传入的才是一个表达式,否则传入的就是变量的情况,就不符合这里的规定了。
-
表达式类型是纯右值,则产生T:



