C++右值引用,左值(lvalue)、将亡值(xvalue)、纯右值(prvalue)

右值引用

C++11增加了移动特性(把资源所有权交出给新对象),基于两个原因:

  1. 在很多时候,对象拷贝后就立即被销毁了,此时移动而非拷贝对象会大幅度提升性能。
  2. 一些类(比如IO类、unique_ptr)包含不能被共享的资源(IO缓冲、指针),所以这些类型的对象不能被拷贝,但可以被移动。

因此引出新的引用类型——右值引用:必须绑定到右值的引用。我们通过 &&来获得右值引用。
右值引用有一个重要性质——只能绑定到一个将要摧毁的对象。因此可以自由地将一个右值引用资源移动到另一个对象。


C++03标准中的左值与右值

C++03标准中将表达式分为左值和右值,并且“非左即右”:

区分一个表达式是左值还是右值,最简便的方法就是看能不能够对它取地址:如果能,就是左值;否则,就是右值。

能标识一个对象的表达式 或 函数 的表达式就是左值表达式。


C++11标准中的表达式分类

右值引用的引入,使得C++11标准中对表达式的分类不再是非左值即右值那么简单。

每个C++表达式只属于三种基本值类别中的一种:左值 (lvalue)、纯右值 (prvalue)、将亡值 (xvalue)

C++11标准中对表达式的分类,简单解释如下:

  • lvalue(左值)仍然是传统意义上的左值;
  • xvalue(eXpiring value)字面意思可理解为生命周期即将结束的值(将亡值),它是某些涉及到右值引用的表达式的值,例如:调用一个返回类型为右值引用的函数的返回值就是xvalue。详细介绍在下面。
  • prvalue(pure rvalue)字面意思可理解为纯右值,传统意义上的右值,例如临时对象字面值常量(字符串字面值除外)等。
  • glvalue(generalized value)广义的左值(泛左值),包括传统的左值和xvalue。
  • rvalue除了传统意义上的右值,还包括xvalue。

依据是否可以移动,值类别可以分为:

  • 左值(lvalue) :指向内存位置的表达式被称为左值(lvalue)表达式,表示对象的身份,不可移动。
  • 右值(rvalue) :右值是不能对其进行赋值的表达式,表示的是对象的值,包含了 将亡值、纯右值(可被右值引用类型匹配),可移动。

C++右值引用,左值(lvalue)、将亡值(xvalue)、纯右值(prvalue)_第1张图片

将亡值

xvalue(expiring value)将亡值
通常指代一个生存周期即将结束的值(因此其资源可以被转移)。是某些涉及到右值引用的表达式的值,根据C++11标准,以下四种情况属于xvalue:

  • 调用函数(无论是隐式还是显式)的结果,该函数的返回类型是对对象类型的右值引用,
  • 对对象类型的右值引用的强制转换,
  • 类成员访问表达式,指定非引用类型的非静态数据成员,其中对象表达式是xvalue,或
  • 指向成员表达式的*指针,其中第一个操作数是xvalue,第二个操作数是指向数据成员的指针。

一般来说,具名的右值引用(named rvalue reference)属于左值,不具名的右值引用(unamed rvalue reference)就属于xvalue,而对函数的右值引用不论是否具名都当做左值处理。
举例:

struct A {
	int m;
};
A&& operator+(A, A);
A&& f();
A a;
A&& ar = static_cast<A&&>(a);

f()、f().m、static_cast(a)、a+a都是将亡值xvalue,ar是左值。



参考:
https://blog.csdn.net/loveyumomo/article/details/23214341
https://www.cnblogs.com/zpcdbky/p/5275959.html
https://www.cnblogs.com/KillerAery/p/12802771.html

你可能感兴趣的:(c++)