左值和右值的概念

         目录

1、什么是左值?

2、什么是右值?

3、左值和右值的区分

4、左值和右值的交叉引用

(1) 左值引用能否引用右值?

(2) 右值引用能否引用左值?


1、什么是左值?

左值是一个表示数据的表达式(如变量名解引用以后的指针)。左值可以取地址和赋值,因为变量一旦被声明,就会在栈上或者堆上开辟一块相应的空间。我们可以取地址来访问到这块空间。

左值引用就是给左值起别名,语法格式数据类型&  别名 = 初始值

应用场景:

  • 作为函数参数,可以减少拷贝:void  func(int& x)
  • 作为函数返回值,可以返回引用:int& func()   
    • 存在缺陷,无法返回临时变量
    • 因为出了作用域,临时变量就被销毁了,一个被销毁的临时变量的引用是无效的
    • 右值引用解决 “ 函数返回临时变量或者对象 ” 的问题
int main()
{
	// p、b、c都是左值
	int* p = new int(0);
	int b = 1;
	const int c = 2;

	// rp、rb、rc是上述左值的引用
	int*& rp = p;
	int& rb = b;
	const int& rc = c;
	return 0;
}

2、什么是右值?

右值也是一个表示数据的表达式,如字面常量表达式返回值函数返回值等。右值不能取地址,因为一般右值都是一些临时变量,比如函数返回值,函数执行完毕以后,会将返回值赋值给寄存器或者一个临时变量,我们无法获取一个临时变量的地址。

右值引用就是给右值起别名,语法格式:数据类型&&  别名 = 初始值

应用场景:

  • 移动构造(解决上述返回临时变量或者对象的问题) 
  • 移动赋值
int main() {
	double x = 1.1, y = 2.2;

	// 以下是常见的右值
	10			// 常量
	x + y		// 表达式的返回值
	func(x, y)	// 函数返回值

	// 以下依次给上述右值起别名
	int&& rr1 = 10;
	double&& rr2 = x + y;
	double&& r33 = func(x, y);

	return 0;
}

注意:const修饰的变量虽然也是常量,但被归为左值。因为在声明的时候,编译器会为其分配一块空间来保存const修饰的常量。

3、左值和右值的区分

不能简单的通过是否为常量 或者 是否可以取地址来区分左值和右值,要根据表达式结果或变量的性质判断。

左值:

  • 普通类型的变量,可以取地址
  • const修饰的常量(原本也是变量,只不过权限变为只读)
  • 引用

右值:

  • 运行结果是一个临时变量或者对象

4、左值和右值的交叉引用

左值引用可以引用左值,右值引用可以引用右值,这个在上面介绍左值和右值的案例中已经体现了,现在问题来了,左值和右值能否交叉引用?

(1) 左值引用能否引用右值?

举例: int&  num = 10;

成立与否:不成立

解决方法:添加const关键字修饰

const int& num = 10;

(2) 右值引用能否引用左值?

举例:int&& rr = a;    // a 是一个变量

成立与否:不成立

解决方法:使用move函数将左值转换成右值

int a = 10;
int&& rr = move(a);    // 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值