C++ 左值、右值、左值引用以及右值引用

一、左值和右值 将亡值

1.左值

左值是一个表示数据的表达式,比如:变量名、解引用的指针变量。一般地,我们可以获取它的地址对它赋值,但被 const 修饰后的左值(常性),不能给它赋值,但是仍然可以取它的地址。

总体而言,凡是能够取地址的值叫做左值。

    int a = 10;           //&a   
	int* ip = &a;         //&ip 
	const int b = 20;     //&b
	const int* bp = &b;   //&bp

2.右值

右值也是一个表示数据的表达式,比如:字面常量、表达式返回值,传值返回函数的返回值(是传值返回,而非传引用返回)右值不能出现在赋值符号的左边且不能取地址

总体而言,不能够取地址的值叫做右值。

    &10;
	&12.23    右值
	&NULL;


  1. &10;&12.23;&NULL;,VS2019 编译报错: “&” 要求左值。原因:右值不能取地址。

3.将亡值 

 将亡值是表达式或函数调用时产生的一个临时量,凡是由内置类型产生的将亡值,它都是一个字面量(只可读不可写),不能够被修改

int main()
{
	int a = 10, b = 20;
	int c = 0;
	c = a + b;//计算值存在 计算结束没了    将亡值
}

 

int Add(int a, int b)
{
	int c = a + b;
	return c;
}

int main()
{
	int x = 0;
	x = Add(12, 23);
}

 

二、左值引用和右值引用 

C++ 语法中就存在引用语法,而 C++11标准中新增了右值引用的语法特性,因此为了区分两者,将C++11标准出现之前的引用称为左值引用。

无论左值引用还是右值引用,都是给对象取别名。

1.左值引用

左值引用就是对左值的引用,给左值取别名

	int a = 10;
	const int b = 20;
	int& ra = a;           //普通引用   
	const int& rca = a;    //常性引用
	const int& rb = b;     //常性引用     

2.右值引用

右值引用就是对右值的引用,给右值取别名。

    //int& rr = 10;
	int&& rr = 10;          //int && right   右值引用

右值引用引用右值,会使右值被存储到特定的位置。
也就是说,右值引用变量其实是左值,可以对它取地址和赋值(const右值引用变量可以取地址但不可以赋值,因为 const 在起作用)。
当然,取地址是指取变量空间的地址(右值是不能取地址的)。 

3.对比与总结

左值引用总结:

  1. 左值引用只能引用左值,不能直接引用右值。
  2. 但是const左值引用既可以引用左值,也可以引用右值。
int main()
{
	int a = 10;
	int& ra = a;
	const int& rca = a;
	//int&& rr = a;          //a是一个左值 右值引用不匹配

	int&& rr = 20;
}
int main()
{
	const int& ra = 10;   //万能引用(不管是左值还是右值都能引用)
	//int tmp=10;
	//const int& ra =tmp;
	//ra += 100;               err

	int&& rr = 10;           //右值引用
	//int tmp=10;                 
	//int &rr=tmp;    


	rr += 100;
   
	int& a = rr;
	//把右值固定到rr上  rr是一个右值引用,
	//右值引用有名字,可以对右值引用取地址(右2名字就能取地址)
	//右值一旦具有名字就变成左值   
	

	//int&& a = rr;           err

}

右值引用总结:

  1. 右值引用只能引用右值,不能直接引用左值。
  2. 但是右值引用可以引用被move的左值。

三、示例

代码如下:

//C++ a:  //类型  值类别   left right  xval;

//void func(int a) { cout << "func(int)" << endl;}                                  //传值
void func(int &b) { cout << "func(int &)left ref" << endl; }                      //左值引用(可以取地址)
void func(const int&c) { cout << "func(const int &c const left ref)" << endl; }   // 万能引用 //常引用
void func(int&& d) { cout << "func(int &&)right ref)" << endl; }                  //右值引用(不能取地址)
int main()
{
   
    func(10);   //int &&d  =>const int &c;
    return 0;

}
int main()
{
    const int x = 10;   //常性
    func(x);   //(const int &b)  
    return 0;

}


int main()
{
    int x = 10;
    func(x);   //产生二义性   //int &b   => (const int &b) 
    return 0;

}

int add(int a, int b)
{
    int c = a + b;
    return c;
}//tmp=c;//将亡值 存在于表达式的临时量

int main()
{
    int a = 10, b = 20;
    int x = add(a, b);



    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值