左值引用_右值引用区分方式,原理及延伸

一.举例理解(可跳过)

定义

左值:一个稳固的房子(有名字)
右值:没有名字的危房

属性

左值拥有左值属性和右值属性
左值属性:是指他的房子名字
右值属性:是指房子里住的人,即对象值
在这里插入图片描述

例如 int a=1;
a有名字,它的名字是a,1没有名字(只有值),那么a为左值,1为右值
房子0x001名字为a,住着1,那么结果仍然是左值(有名字的房子即左值)

二.左值和右值

1. 定义

左值(lvalue: locator value):存储在内存中,有明确存储地址(可寻址)的数据

右值(rvalue: read value):提供数据值的数据(不一定可以寻址,可能存在寄存器中)

判断方法:

有名称,能获取到地址的值就为左值,不能的就是右值

2. 左值引用

定义:能指向左值,不能指向右值的就为左值引用

	int x=5;
	int & ref=x;//左值引用指向左值
	int & reb=4;//报错,左值引用指向右值

3. 右值引用

定义:可指向右值,不能指向左值

	int &&ref=5;//不报错
	int a=5;
	int &&reb=a;//报错,不能指向左值
&&理解

&&为右值引用的声明符号,允许绑定到临时对象上(即危房上)

底层实现原理:(以int &&a=10;举例)
  1. 编译阶段,编译器将int &&a解析为右值引用类型的变量a;
  2. 初始化阶段,10作为右值赋值给a;
  3. 内存中,a被分配一个地址,并将该地址指向存储值为10的临时对象
int main(){
	int &&a = 1;//右值引用,a为左值
	int b=10;//左值
	int &&b1=b;//报错,不能将左值转化为右值引用

}

4. move函数作用

上面提到,不能将左值转化为右值引用(右值引用指向左值),那什么方式可以实现呢?
可以调用move来实现

int b=10;
int &&b1=std::move(b);
原理:

move告诉编译器,我们有一个左值,但是我希望像右值一样处理它
调用move意味着承诺:除了对b赋值或销毁外,我们将不使用它。

使用场景

用于STL和自定义类中实现移动语义 ,避免拷贝。

  • STL实现
int main(){
	string str1="feifei";
	vector<string> vec;
	
	vec.push_back(str1);
	vec.push_back(std::move(str1));//避免str1失去原有值,变成空字符串
	vec.emplace_back(std::move(str1));//str1失去原有值
	vec.emplace_back("felix");
}
	
void push_back(const value_type& val);
void push_back(value_type&& val);
void emplace_back(Args&&... args);


  • 自定义实现
class AY{
public:
	....
	AY(AY&&temp_ay){
		data1=temp_ay.data1;
		size1=temp_ay.size1;
		temp_ay.data1=nullptr;
	}
	int *data1;
	int size1;
}

int main(){
	AY a;
	....
	AY b(std::move(a));
}

这些就涉及深拷贝浅拷贝问题了,可以通过移动构造函数实现,移动构造函数具体实现方式可参考

https://blog.csdn.net/weixin_44788542/article/details/126284429

5. const引用

C++ 允许常量引用(const 引用)来绑定到临时的右值(包括整数常量)上

int main(){
	int && a=1;
	int *c=3;//报错
	const int &f =3;//不报错,const为保护罩,将对象保护起来
	const int b=100;
	int &b2=b;//报错 非常量左值引用不支持引用常量左值

实现原理:
int & a=1;//报错 原因:1为立即数,存放在寄存器中,执行完就被销毁

const int &a=1;//不报错  
//原因:内存中产生一个临时变量,a引用这个临时变量,在整个 a 的作用域内,临时对象将继续存在,直到 a 的作用域结束。
//相当与
const int b =10;
const int &a=b;

三. 延伸

const 和&的关系
int a=10;
int &b =a;
b=20;

//等同于
int a=10;
int * const b=&a;
*b=20;
auto &&是万能引用

&&不是右值引用吗,为什么可以引用左值?
原因在于auto;

auto 关键字推导变量类型时,如果变量被初始化为一个右值,auto 推导出的类型是右值引用;而当变量被初始化为一个左值时,auto 推导出的类型是左值引用。
通过下面这个例子就很好理解了

int x = 5;
auto &&ref1 = x; // 推导为 int&
auto &&ref2 = 5; // 推导为 int&&

上面很多都是概念知识,具体应用可参考下面博文,强推!!!

https://sxyandqx.blog.csdn.net/article/details/130955297

参考鸣谢
https://www.bilibili.com/video/BV1LY4y1F7Jn
https://blog.csdn.net/jiexianxiaogege/article/details/133106476
c++ primer(第五版)
https://zhuanlan.zhihu.com/p/335994370

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值