左右值概念

简单理解

左值:赋值运算符左边的变量,可以接受右边值,例如 int a = 10; a就是一个左值右值:赋值运算符右边的值,这个值可以是一个变量也可以是一个常量,例如 int a = 10; 10就是一个右值,并且是个常量。

深究概念

C++中有“左值”、“右值”的概念,C++11以后,又有了“左值”、“纯右值”、“将亡值”的概念。关于这些概念,许多资料上都有介绍,本文在拾人牙慧的基础上又加入了一些自己的一些理解

要说清“三值”,首先要了解 ”表达式“ , “值类别” , “类型”

表达式

由运算符和运算对象成的计算式(类似于数学上的算术表达式)。

表达式是可求值的,对表达式求值将得到一个结果。这个结果有两个属性:类型和值类别(value categories)。

类型

如 int char

值类别

通俗理解就是值的属性, 在此讨论此属性专指“左值”、“纯右值”、“将亡值”

  • 左值(left value,lvalue),
  • 将亡值(expiring value,xvalue),
  • 纯右值(pure rvalue,prvalue)。

其中,左值和将亡值合称为“泛左值”(generalized lvalue, glvalue),纯右值和将亡值合称为“右值”(rvalue)

至此,它们之间的关系如下。

为了好理解, 咱们头脑中可以将如上图中左下角的lvalue想象为plvalue。

左值 lvalue

个人理解: 可以通过程序代码,直接访问操作。 比如: int a = 10; a变量是内存存储的别名,可通过别名进行操作。

纯右值 prvalue:

定义

满足下列条件之一

1、本身就是纯粹的字面值,如3,false,12.13 ;  注意:字符串不是纯右值2、求值结果相当于字面值或是一个不具名的临时对象

特性

纯右值不具有多态

将亡值 xvalue

在C++11之前的右值和C++11中的纯右值是等价的。C++11中的将亡值是随着右值引用的引入而新引入的。换言之,“将亡值”概念的产生,是由右值引用的产生而引起的,将亡值与右值引用息息相关。所谓的将亡值表达式,就是下列表达式:

1、 返回右值引用的函数的调用表达式 ,  如 static_cast(t); 该表达式得到一个 xvalue
2、 转换为右值引用的转换函数的调用表达式 如:std::move(t)、static_cast(t)

在C++11中,我们用左值去初始化一个对象或为一个已有对象赋值时,会调用拷贝构造函数或拷贝赋值运算符来拷贝资源(所谓资源,就是指new出来的东西),而当我们用一个右值(包括纯右值和将亡值)来初始化或赋值时,会调用移动构造函数或移动赋值运算符来移动资源,从而避免拷贝,提高效率。当该右值完成初始化或赋值的任务时,它的资源已经移动给了被初始化者或被赋值者,同时该右值也将会马上被销毁(析构)。
也就是说,当一个右值准备完成初始化或赋值任务时,它已经“将亡”了。而上面1和2两种表达式的结果都是不具名的右值引用,它们属于右值。

右值引用

上面提到右值引用 , 那么什么是右值引用呢, 大家看下移动构造函数 和 移动赋值运算符的函数声明

 //  移动构造// String s(将亡值对象)String(String&& s) : _str(nullptr){swap(_str,s._str);}// 移动赋值String& operator=(String&& s){swap(_str,s._str);return *this;}

可见带两个&的即是右值引用。

将亡值定义了这样一种行为:具名的临时值、同时又能够被move。

泛左值

泛左值(glvalue, generalized lvalue),又称为广义左值,是具名表达式,对应了一块内存。glvalue有lvalue和xvalue两种形式。

一个表达式是具名的,则称为glvalue,例子如下:

1. struct S{
2. ​    int n;
3. };
4. S fun();
5. S s;
6. s;
7. std::move(s);
8. fun();
9. S{};
10. S{}.n;

在上述代码中:

  • 定义了结构体S和函数fun()
  • 第5行声明了类型为S的变量s,因为其是具名的,所以是glvalue
  • 第6行同上,因为s具名,所以为glvalue
  • 第7行中调用了move函数 ,将左值s转换成xvalue,所以是glvaue
  • 第9行中,fun()是不具名的,是纯右值,所以不是glvalue
  • 第10行中,生成一个不具名的临时变量,是纯右值,所以不是glvalue
  • 第11行中,n具名,所以是glvalue

glvalue的特征如下

可以自动转换成prvalue
可以是多态的
可以是不完整类型,如前置声明但未定义的类类型

举例

int a = 1;
int &rb = a; // b为左值引用
int &&rrb = a; // 错误,a是左值,右值引用不能绑定左值
int &&rrb1 = 1; // 正确,1为右值
int &rb1 = i * 2; // 错误,i * 2是右值,而rb1位左值引用
int &&rrb2 = i * 2; // 正确
const int &c = 1; // 正确
const int &c1 = i * 2; // 正确

以上是值类别介绍, 通过如上介绍, 可了解到右值引用声明的变量即是将亡值了, 但是也具名, 且特性上还可以是多态的,所以此时这个将亡值跟左值也无两样,而此时还未涉及到移动,所以更无析构的说道了,就是一个正常的变量。

而为什么说是将亡值呢, 是因为C++大多数的使用的场景是作为函数参数说明, 特别是移动构造函数和移动赋值函数,而此时确实是将亡了,因为此时内存所属权马上被移交,即之前的右值引用声明的名称不在可用(因为移交了内存标签,此时变量名不能再代表内存对象了)

左值右值将亡值泛左值相关推荐

  1. php如何从左往右轮播,js实现从左向右滑动式轮播图效果

    轮播图就是让图片每隔几秒自动滑动,达到图片轮流播放的效果.轮播图从效果来说有滑动式的也有渐入式的,滑动式的轮播图就是图片从左向右滑入的效果,渐入式的轮播图就是图片根据透明度渐渐显示的效果,这里说的是实 ...

  2. html怎么从左到右设置颜色,使用CSS从左到右填充文本颜色(Text colour fill from left to right using CSS)...

    使用CSS从左到右填充文本颜色(Text colour fill from left to right using CSS) 我试图动画有".popUpWord"类的文本. 在悬停 ...

  3. 【程序设计】浅析编程语言的区间为何常是左闭右开

    高中大家都学过区间--闭区间.开区间.左闭右开区间.左开右闭区间. 区间在Java里也有体现.比如用解析字符串子串的形式来提取身份证的信息,提取子串就相当于截取一个区间. 用一门语言,用的久应该会对它 ...

  4. Python之从左到右依次输出数字上每位的数

    文章目录 写在开头的话 从左到右依次输出每位上的数 题目 分析 方法一(将用户输入转化为整数) 方法二(将用户输入作为字符串处理) 写在最后的话: 这里是一段防爬虫文本,请读者忽略. 本文原创首发于C ...

  5. css3 div从左到右滑入

    css3 div从左到右滑入 实现div从左到右滑入,代码如下: // lToR定义一个动画 @keyframes lToR{from {width: 0px;}}@-moz-keyframes lT ...

  6. c++ 左值 广义左值 右值 纯右值 将亡值

    为什么C/C++等少数编程语言要区分左右值? 历史原因: C语言作为一门古老的编程语言,其设计初衷是为了在硬件资源有限的系统上进行高效的编程,因此其语法和语义设计相对较简单.左值和右值的概念最初是由C ...

  7. C++11 左值 右值

    在C++11中所有的值必属于左值.右值两者之一. C++98 左值(lvalue),可以放在赋值运算符=左边的变量或者表达式,有名字,可以取地址. 右值(rvalue),临时变量值(非引用返回的函数返 ...

  8. 表达式左值右值(C++学习)

    左值右值是表达式的属性,该属性称为 value category.按该属性分类,每一个表达式属于下列之一: lvalue left value,传统意义上的左值 xvalue expiring val ...

  9. 左值右值,左值引用和右值引用及其用途

    目录 1.左值和右值 2.引用 (1)左值引用 (2)右值引用 3.左值引用的用途 (1)作为复杂名称变量的别名 (2)用于rangeFor循环 (3)避免复制大的对象 (4)参与函数中的参数传递 4 ...

最新文章

  1. 《QTP自动化测试进阶》(1)
  2. CentOS 7安装GNOME图形界面并设置默认启动
  3. Yii的action
  4. 【SICP练习】79 练习2.51
  5. 这是Blazor上传文件的最佳方式吗?
  6. 果园机器人是什么文体_果园机器人课文原文
  7. C++网易云课堂开发工程师--转换函数
  8. 富爸爸系列 -- 《财务自由》学习笔记之三
  9. 光电自动避障小车_AGV机器人:基于视觉避障的理论基础
  10. SSL之父称SSL不会因被攻击而失去生命力
  11. 皮尔特沃夫服务器在什么位置,你知道LOL大区的服务器在哪吗?很有可能就在你家旁边...
  12. 怎么在python输出图片_python怎么输出图片
  13. java excel 数组公式_教你如何快速学习Excel数组公式及运用
  14. 抖音最火刺激战场S5新赛季灵敏度:用过的都说好,建议收藏
  15. win10计算机跑分,Win11对比Win10系统性能测试,看完跑分结果还等发布会吗?
  16. 冷战 (并查集按秩归并)
  17. H264 profile 及帧类型介绍
  18. Asp.net夜话之二:asp.net内置对象
  19. [亲测可行]Ubuntu16.04+opencv3.4+opencv_contrib+cuda9.0安装
  20. 2022最新IntellJ IDEA的mall开发部署文档

热门文章

  1. jasperreport mysql_JasperReport报表设计
  2. Windows2000源代码下载 (转)
  3. 电子计算机比尔盖茨和微软品牌,尉迟:比尔盖茨卖安全套 牌子不能叫微软
  4. 基于深度学习的近红外掌纹识别原型系统设计与实现
  5. 我购买的计算机书籍清单
  6. 边缘计算:客户端 + 人工智能
  7. H3C SSL weiPN基本配置(内网OSPF协议)
  8. 网络工程师在现实中的意义
  9. (01)ORB-SLAM2源码无死角解析-(24) 单目SFM地图初始化→CreateInitialMapMonocular()-细节分析:尺度不确定性
  10. oracle是否支持gb18030,检测输入法是否支持GB18030标准