首页 > 其他分享 >左值、右值、左值引用和右值引用

左值、右值、左值引用和右值引用

时间:2023-04-26 09:58:30浏览次数:32  
标签:return 右值 int 左值 引用 func

 

文章目录
左值和右值
什么是左值和右值?
举例说明
程序分析
左值引用和右值引用
什么是左值引用和右值引用?
左值引用
右值引用 (important!!!)
左值和右值的转换
左值变右值
右值变左值
左值和右值
什么是左值和右值?
按照我们常规理解左值就是在等号左边的值,右值是等号右边的值。如果你要这么理解,你就会发现遇到++i或i++这一类的语句你就开始混乱了!

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

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

举例说明
左值:

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

x++;
y+3;
123;
//y+3这个值会被计算,但是没有被承接到,
//后来即便我们再用y+3去获得这个临时的值,大小是一样的,
//但不是我上次计算的那个值,我又经过了以此计算的到的。

//x++;这个从底层去分析:
//x++会产生一个临时变量,用来保存x+1的值,
//等到语句结束,将x+1赋值给x.
//但是语句没结束时,这个临时变量时在寄存器中保存的,一个计算结果的临时变量,
//此时是不可寻址的!!即右值。

1
2
3
4
5
6
7
8
9
10
11
12
13
程序分析
#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;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
输出结果为:

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 !
1
2
3
4
5
6
7
左值引用和右值引用
什么是左值引用和右值引用?
什么是引用?
引用表示为符号“&”;
引用就是用另外的名称来索引到该变量。

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

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

1
2
3
4
5
6
7
8
9
10
11
12
分析:

其中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;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
通过关闭返回值优化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
1
2
3
4
5
6
7
8
9
使用对象A直接去承接返回值
int main(){
A a(1),b(3);
A c = a+b; //此时用A类对象C承接返回值。

cout << "====================="<<endl;
return 0;
}
1
2
3
4
5
6
7
关闭返回值优化,得到结果:

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
//可以看到产生大量的拷贝构造,临时变量我没有救火,卫视拷贝了一个拿来用。
1
2
3
4
5
6
7
8
9
10
11
12
使用右值引用且承接返回值
int main(){
A a(1),b(3);
A &&c = a+b; //右值引用

cout << "====================="<<endl;
return 0;
}
1
2
3
4
5
6
7
关闭返回值优化,得到结果:

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用了,没产生多余的拷贝构造。
1
2
3
4
5
6
7
8
9
10
右值引用就是把右值变成左值,通常实在C++返回值上,对于自定子类的重复拷贝做了重要改善,大大提高了C++的效率。
右值引用的概念是C++中的重要概念!!!!。

左值和右值的转换
左值变右值
通过move(class value)函数
move()可以通过man手册查看。

通过通用转换 forward<B&&>
通过引用const &
变成只读,也是不能放在等号左边

右值变左值
通过右值引用&&

通过通用转换 forward<B&>
————————————————
版权声明:本文为CSDN博主「四库全书的酷」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_46535567/article/details/124568380

 

标签:return,右值,int,左值,引用,func
From: https://www.cnblogs.com/im18620660608/p/17354730.html

相关文章

  • 左值、左值表达式、左值引用 C++
     本文topics什么是左值和右值什么是左值表达式、右值表达式引用的分类之前学习Java的时候只记得在赋值表达式左边的就是左值,右边的就是右值。这个说法没有错,但今天又在C++中有学习到了关于左右值得概念,在此梳理了一些这些知识点。左值和右值左值:左值是一个对象或变量,可以代表......
  • 不同语言加载不同字号,设置到资源文件中,进行引用
    在资源文件夹创建一个类在App.xaml文件中引用这个类的空间命名,并把这个类添加到资源在页面中应用在使用其他语言时,开启新的子线程依然会使用区域语言.net4.5后使用可以一次性解决varculture=newCultureInfo("en-US");    CultureInfo.DefaultThreadCurrent......
  • C++基础3: 引用
    前言本篇首先回顾指针的概念,用C指针的缺陷引出C++中的引用,然后对引用进行说明比如,什么是引用?引用解决指针什么问题?引用的特性和使用等等1.指针什么是指针指针是内存单元的地址,口语中的指针实际上是指针变量,存储地址的变量#include<stdio.h>intmain(){ i......
  • Eclipse打JAR包引用的第三方JAR包找不到的问题。
    我的程序里引用了别的JAR包在ECLIPSE里运行正常我想把我的程序打个JAR包打包的时候把引用的包也打进去了可运行程序确总是找不到我引用的包是不是路径的问题?急死我了快    解决方案:在你的项目文件夹下建一个META-INF文件夹里面新建一个MANIFEST.MF的文件内容大至如......
  • PHP中的引用参数的函数
    前言php的引用(就是在变量或者函数、对象等前面加上&符号)在PHP中引用的意思是:不同的名字访问同一个变量内容。与C语言中的指针是有差别的。C语言中的指针里面存储的是变量的内容在内存中存放的地址,函数的引用返回多用在对象中引用参数的函数格式说明如下代码所示:voidfunName(array......
  • BeanUtils.copyProperties()深拷贝失效,对象值被引用改变
    之前就想一个深拷贝的解决方案,尝试用BeanUtils.copyProperties实现现在发现无法实现,两个变量引用位置相同最好自己实现一个工具类。之前在脉脉上看到有人提问,回答是用fastjson序列化解决的 Studentclone=JSONObject.parseObject(JSONObject.toJSONBytes(student),Stude......
  • 为什么再html页面引用element复选框,只有名称值,没有复选框
    问题描述我引入了el-checkbox之后,发现浏览器页面只是显示里面的文字,并没有显示出来我想要看到的相应样式问题解决经过一定的百度查证可知,使用Element-UI组件时,我们需要用div标签将其包裹起来;然后使用script标签定义一下div里面的id属性,然后才能够引用到这个el-标签,让其中的样......
  • Unity框架:JKFrame2.0学习笔记(十)——自动生成资源引用代码(2)
    前言上一篇记录了自动生成资源引用代码的内部实现,主要是针对addressable的资源系统的,为了在加载时不会因为名字写错,加载错,也更加方便的使用addressable加载,这一篇记录下如何使用。如何使用之前看过,在编辑器中添加了工具按钮我们可以在addressable的groups面板上添加几个测试资源我......
  • MachineLearningNote (sklearn 学习总结)---引用
    MachineLearningNote(sklearn学习总结)---引用: https://github.com/LeBron-Jian/MachineLearningNotePython机器学习笔记:sklearn库的学习地址:https://www.cnblogs.com/wj-1314/p/10179741.htmlPython机器学习笔记:使用sklearn做特征工程和数据挖掘地址:https://www.cnblog......
  • jvm之强软弱虚引用
    强软弱虚引用在java中,除了基本数据类型的变量外,其他所有的变量都是引用类型,指向堆上各种不同的对象。在jvm中,除了我们常用的强引用外,还有软引用、弱引用、虚引用,这四种引用类型的生命周期与jvm的垃圾回收过程息息相关。那么这四种引用类型有什么区别?具体使用场景是什么?所有引用类型......