C++11的右值引用(一)——左值(lvalue),纯右值(prvalue)和将亡值(xvalue)

来源:互联网 发布:unity3d开发流程 编辑:程序博客网 时间:2024/05/22 06:41

基本概念

C++11之前只有左值和右值的概念:lvalue,rvalue。左值可以取地址,右值不能取地址。
但是C++11之后又划分的更加详细了,分为左值(lvalue),纯右值(prvalue)还有将亡值(xvalue),关系如下:
这里写图片描述
之前是lvalue的地方还是lvalue,之前是rvalue的地方变成了prvalue,而xvalue则是新加入的

  • lvalue:左值,即传统意义上的左值。
  • xvalue(expiring value):x值(中间值?),指通过“右值引用”产生的对象。这里x可以理解为即将消失(expiring),也可理解为中间(横跨左值和右值)。
  • prvalue(pure rvalue):纯右值,即传统意义上的右值。

prvalue(pure rvalue):纯右值,即传统意义上的右值。
两种复合类型:
glvalue(general lvalue):泛左值,由左值和x值构成。泛左值具有动态的类型和对象属性。
rvalue:右值,由x值和纯右值构成。右值具有潜在的可移动性。
关于右值引用:

  • 具名右值引用被视为左值。
  • 无名右值引用被视为x值。
  • 对函数的右值引用无论具名与否都将被视为左值。

    1. 把右值引用类型作为返回的函数或者重载操作符。例如, std::move(x);
    2. a[n], 内置的下标[subscript]表达式,其中,‘a’是一个右值数组。
    3. a.m, 对象的取成员变量表达式。其中,‘a’是一个右值,‘m’ 是非引用类型的非静态数据成员。
    4. a.*mp, 对象的成员指针表达式[the pointer to member of object expression]。其中,‘a’是右值,‘mp’是指向数据成员的指针。

lvalue+xvalue构成了glvalue(泛左值)都是有「身份」的值
prvalue+xvalue构成了rvalue(右值)都能被「移动」,右值都不能被取地址【至于什么是移动(move)下篇帖子再讲吧】

一个需要注意的地方

作为函数参数[argument],如果有两个重载函数可用[avaliable],其中一个把右值引用作为参数[parameter],另一个把常左值引用作为参数,那么右值会绑定[bind to]那个把右值引用作为参数的重载函数。(因此,在拷贝构造函数和移动构造函数都可用[available]的情况下,右值参数会调用[invoke]移动构造函数,拷贝赋值符号和移动赋值符号与之类似。)

记得移动构造函数的试用条件吗,好好把上面这句话看一下。
另外关于移动构造函数,还有一句话就是:如果没有显示定义移动构造函数,但是显示的定义了复制构造函数,那么移动构造函数就不存在了

参考资料

关于这个问题cppreference写的非常详细了
Value categories
下面这个上cppreference的翻译版:
cppreference.com关于值类型的详细解读:lvalue,rvalue,xvalue,prvalue,glvalue
还有一个更详尽的官方指南:
A Taxonomy of Expression Value Categories

关于移动语义有如下参考:
如何理解C++中的move语义?

看完这个你还不理解右值引用和移动构造 你就可以来咬我(上)

0 0