文章目录

  • 左值和右值
    • 什么是左值和右值?
    • 举例说明
    • 程序分析
  • 左值引用和右值引用
    • 什么是左值引用和右值引用?
    • 左值引用
    • 右值引用 (important!!!)
  • 左值和右值的转换
    • 左值变右值
    • 右值变左值

左值和右值

什么是左值和右值?

按照我们常规理解左值就是在等号左边的值,右值是等号右边的值。如果你要这么理解,你就会发现遇到++ii++这一类的语句你就开始混乱了!

其实左值和右值是我们习惯性的叫法,他的全拼应该是:
左值是:locator value(可寻址的数据)
右值是:read value(不可寻址的数据或用来读的数据)

我们常规去理解,应该理解为:
在该程序语句之后能再找到该值,就是左值;否则就是右值。就是不可寻址!

举例说明

左值:

++x;
y*=33;
//这里面++x是直接对x自增,我们得到的值就是x的值,
//是可以后来直接使用x这个变量去使用这个值的。

右值:

x++;
y+3;
123;
//y+3这个值会被计算,但是没有被承接到,
//后来即便我们再用y+3去获得这个临时的值,大小是一样的,
//但不是我上次计算的那个值,我又经过了以此计算的到的。//x++;这个从底层去分析:
//x++会产生一个临时变量,用来保存x+1的值,
//等到语句结束,将x+1赋值给x.
//但是语句没结束时,这个临时变量时在寄存器中保存的,一个计算结果的临时变量,
//此时是不可寻址的!!即右值。

程序分析

#include<iostream>
#include<string>#define func(x)  _func(x,"func("#x")")
using namespace std;void _func(int &x,string str){ //左值值重载_func()cout << str << "left value !"<<endl;return ;
}void _func(int &&x,string str){ //右值重载_func()cout << str << "right value !"<<endl;return ;
}
int main(){int x = 3;int y = 4;func(123);func(x++);func(++x);func(x*3);func(x*=3);func(y/4);func(y/=4);return 0;
}

输出结果为:

func(123)right value !
func(x++)right value !
func(++x)left value !
func(x*3)right value !
func(x*=3)left value !
func(y/4)right value !
func(y/=4)left value !

左值引用和右值引用

什么是左值引用和右值引用?

  • 什么是引用?

引用表示为符号“&”;
引用就是用另外的名称来索引到该变量。

左值引用

左值引用得到的就是还是一个左值。

#include<iostream>
using namespace std;
int main(){int a = 10;int &b = a;cout << b << endl; //输出为10b = 5;cout << a << endl; //输出为5cout << &a << " " << &b << endl; //a和b的地址相同。return 0;
}

分析:

其中a和b都是左值,他们都是一个变量,且都是表示相同地址上存放的某个int类型的数。
且此时输出a和b的地址是一样的。

右值引用 (important!!!)

右值引用的使用常常在自定义类中,可以查看该博文去理解。

右值引用操作符为 “&&”;
右值引用得到的是一个左值。
右值引用通常将一个临时变量拿过来用。
右值引用最主要的功能是解决的是自定义类重复构造冗余的问题。

下面三种情况就告诉你什么时右值引用?为什么要有右值引用?

  • 未使用右值引用时且不去承接返回值
//"test2.cpp"
#include<iostream>
using namespace std;class A{int x;public:A(int x = 0):x(x){cout << this << ":default constructor"<<endl;}A(const A&a):x(a.x){cout << this << ":copy constructor"<<endl;}A operator+(const A& a){return A(x+a.x);}~A(){cout << this << ":destructor"<<endl;}
};int main(){A a(1),b(3);a+b;cout << "====================="<<endl;return 0;
}

通过关闭返回值优化g++ test2.cpp -fno-elide-constructor ,可以看到结果:

0x7fffbe1e127c:default constructor   //A a(1)
0x7fffbe1e1280:default constructor   //A b(3)
0x7fffbe1e1244:default constructor   //A(a.x+b.x)
0x7fffbe1e1284:copy constructor      //return A(a.x+b.x)->返回值会调用拷贝构造给承接a+b的变量A。代码中没有承接到a+b,会立马构析。
0x7fffbe1e1244:destructor
0x7fffbe1e1284:destructor
=====================   //程序结束后构析
0x7fffbe1e1280:destructor
0x7fffbe1e127c:destructor
  • 使用对象A直接去承接返回值
int main(){A a(1),b(3);A c = a+b;   //此时用A类对象C承接返回值。cout << "====================="<<endl;return 0;
}

关闭返回值优化,得到结果:

0x7ffd08697558:default constructor
0x7ffd0869755c:default constructor
0x7ffd08697524:default constructor  //A(a.x+b.x)
0x7ffd08697564:copy constructor  //return A(a.x+b.x)的临时对象
0x7ffd08697524:destructor  ~A(a.x+b.x)
0x7ffd08697560:copy constructor  //A C = (return A(a.x+b.x)) 拷贝构造
0x7ffd08697564:destructor
=====================
0x7ffd08697560:destructor
0x7ffd0869755c:destructor
0x7ffd08697558:destructor
//可以看到产生大量的拷贝构造,临时变量我没有救火,卫视拷贝了一个拿来用。
  • 使用右值引用且承接返回值
int main(){A a(1),b(3);A &&c = a+b;  //右值引用cout << "====================="<<endl;return 0;
}

关闭返回值优化,得到结果:

0x7ffc22247b74:default constructor
0x7ffc22247b78:default constructor
0x7ffc22247b44:default constructor
0x7ffc22247b7c:copy constructor
0x7ffc22247b44:destructor
=====================
0x7ffc22247b7c:destructor
0x7ffc22247b78:destructor
0x7ffc22247b74:destructor
//可以发现return A(a.x+b.x)产生的临时对象直接被C用了,没产生多余的拷贝构造。

右值引用就是把右值变成左值,通常实在C++返回值上,对于自定子类的重复拷贝做了重要改善,大大提高了C++的效率。
右值引用的概念是C++中的重要概念!!!!。

左值和右值的转换

左值变右值

  • 通过move(class value)函数

move()可以通过man手册查看。

  • 通过通用转换 forward<B&&>
    • 通过引用const &

变成只读,也是不能放在等号左边

右值变左值

  • 通过右值引用&&

  • 通过通用转换 forward<B&>

左值、右值、左值引用和右值引用相关推荐

  1. C++/C++11中左值、左值引用、右值、右值引用的使用

    C++的表达式要不然是右值(rvalue),要不然就是左值(lvalue).这两个名词是从C语言继承过来的,原本是为了帮助记忆:左值可以位于赋值语句的左侧,右值则不能. 在C++语言中,二者的区别就没 ...

  2. 39.左值、左值引用、右值、右值引用

    1.左值和右值的概念 左值是可以放在赋值号左边可以被赋值的值:左值必须要在内存中有实体:          右值当在赋值号右边取出值赋给其他变量的值:右值可以在内存也可以在CPU寄存器.       ...

  3. 左值、右值、左值引用、右值引用

    1. 左值 左值(lvalue,left value),顾名思义就是赋值符号左边的值,可以取地址.准确来说,左值是表达式(不一定是赋值表达式)后依然存在的持久对象. 可以将左值看作是一个关联了名称的内 ...

  4. 左值和左值引用、右值和右值引用

    左值和左值引用.右值和右值引用 - _yanghh - 博客园 (cnblogs.com)

  5. 的引用_左值、右值、左值引用、右值引用

    [导读]:本文主要详细介绍了左值.右值.左值引用.右值引用以及move.完美转发. 左值和右值 左值(left-values),缩写:lvalues 右值(right-values),缩写:rvalu ...

  6. c 表达式必须是可修改的左值_C++中的左值,右值,左值引用,右值引用

    童帅 2020-2-22 文中的"表达式"都是指赋值表达式 左值,右值,左值引用,右值引用 到底是什么 左值和右值 int a = 10; int b = 5; int c = a ...

  7. 【C++11】左值引用和右值引用

    目录 一.新的类功能 1.新的默认成员函数 2.类成员变量初始化 3.强制生成默认函数的关键字default 4.禁止生成默认函数的关键字delete 二.左值和右值 1.左值和左值引用 2.右值和右 ...

  8. C++ 左值引用和右值引用

    转自叶余的知乎文章,如果侵权请告知删除! https://zhuanlan.zhihu.com/p/97128024 左值引用 先看一下传统的左值引用. int a = 10; int &b ...

  9. 左值、左值引用、右值、右值引用

    关于左值 右值示例 可看这里 1.左值和右值的概念 左值是可以放在赋值号左边可以被赋值的值:左值必须要在内存中有实体:          右值当在赋值号右边取出值赋给其他变量的值:右值可以在内存也可以 ...

  10. C++ 左值与右值 左值引用与右值引用

    1 左值与右值 左值: 是可以取地址有名字的,非临时的都是左值.在内存中必须有实体. 右值: 不能取地址,没有名字,临时值是右值.在内存或者在寄存器中. 通俗点讲: 右值只能放在 = 号的右边 左值可 ...

最新文章

  1. js中cookie的使用详细分析
  2. 祁阳一中2021年高考成绩查询,祁阳一中2019高考成绩喜报、一本二本上线人数情况...
  3. 谷歌研究院出品:高效 Transformer 模型最新综述
  4. 【错误记录】Google Play 上架报错 ( 此版本不符合 Google Play 关于提供 64 位版本应用的要求 )
  5. python之pygame安装教程_Python中pygame安装方法图文详解
  6. Hadoop之企业案例分析
  7. JVM体系结构:JVM类加载器和运行时数据区
  8. 前端学习(2991):vue+element今日头条管理--使用vue-cli解决问题
  9. [生产库实战] 如何使用触发器对生产库上亿级大表进行实时同步
  10. 详述MySQL事务及ACID特性的实现原理
  11. 关于input样式的一些技巧
  12. 【Python之旅】第四篇(二):Python异常处理与异常捕捉
  13. Win7系统开机动画设置
  14. react录制mp3格式音频,输出二进制数据流向后台请求音频的url
  15. 色纯度(purity)主波长(WD)计算软件(升级版)
  16. flash小黄油安卓_安卓10 Root教程+一加官方字体优化包
  17. Cesium添加百度地图
  18. 谈谈笔者是怎么拿到HFish社区活动仅有的500京东E卡
  19. 魔方机器人之SVM算法识别魔方颜色
  20. 华为魔术2手机拆机图解_荣耀Magic2做工如何?荣耀Magic2拆解图解评测 (全文)

热门文章

  1. es基本语句详解 查询语句详解
  2. 操作系统——输入/输出(I/O)管理
  3. 第002课 ubuntu环境搭建和ubuntu图形界面操作(免费)
  4. 解决手机设备无法adb连接
  5. 前端初学者----网页中的表格
  6. eletree append方法添加子节点
  7. 通过twilio模块发送短信
  8. 苹果iPad mini等系列产品10月发布会实况(上)
  9. 2012年度最佳Web前端开发工具和框架
  10. 视频:搜狗CEO王小川终于把区块链讲通透了