C语言中文右值引用,C++拾遗--引用(左值引用、右值引用)

前言

引用就是别名(alias)。所谓别名,就是对已存在的对象另起一个名字。本身含义并不难理解,但与其它概念一组合,就成了使用难点。再加上新标准提出了新的一种引用-右值引用,引用这一概念就变得更加难以理解和使用。

正文

随着新标准(新标准往往就是新的技术)的提出,引用这一概念分成两类:左值引用、右值引用。其中左值引用是最常用的一种,而右值引用则是语言使用上的一种革新。

1.左值引用

左值引用的基本语法

Type &引用名 = 左值表达式;

#include

using namespace std;

int main()

{

int a = 10;

//ra是a的引用(别名),相当于把ra与a绑定。

int &ra(a);

cout << ra << "  " << (void*)&ra << "  " << (void*)&a << endl;

cin.get();

return 0;

}

运行

b92bc0a3ca6b76f273b617b87eb33e2c.png

引用的基本规则

声明引用的时候必须初始化,且一旦绑定,不可把引用绑定到其他对象。

对引用的一切操作,就相当于对原对象的操作。

2.右值引用

以上是最常见的引用方式,我们称之为左值引用。为了顺利区分左右值引用的概念,我们先来看下左右值的概念。

首先,左右值是表达式的属性。何为表达式?表达式由一个或多个运算对象组成。字面值和变量是最简单的表达式。

一个对象被用作右值时,使用的是它的内容(值),被当作左值时,使用的是它的地址。

int a = 1;

a + 1;    //a + 1 是表达式

在C++旧标准中,我们可以引用a,但却无法引用a+1,这是为什么呢?

这是因为,变量a被创建后,在它的作用域内是一直存在的。如此一来,它的引用是有存在意义的。而a+1不是一个对象,在运算中临时存在于寄存器中,而寄存器中的值是时刻被刷新的,创建a+1的引用显得没有任何意义。为了成功的使用类似于a+1这种右值的引用。C++新标准提出了区别于以往的引用-右值引用。

右值引用的基本语法

Type &&引用名 = 右值表达式;

#include

using namespace std;

int main()

{

int a = 10;

//右值引用

int &&ra(a+1);

cout << ra << ends << (void*)&ra << ends << (void*)&a << endl;

ra++;

cout << ra << endl;

cin.get();

return 0;

}

运行

a9277f190bb4ed2a314845839a0d07a0.png

对右值引用的一种可能的内部实现解释

int a = 1;

int *p = new int(a + 1);

int &ra = *p;

delete p;      //不再使用引用了,动态内存的释放由C++自动管理

其中第二、三两句就对应右值引用:int &&ra(a+1);

3.引用作为函数参数

引用作为函数参数时,有着指针一样的功能。

#include

using namespace std;

void fun(int &ra)

{

cout << ra << ends << (void*)&ra << endl;

ra++;

}

int main()

{

int a = 10;

fun(a);

cout << a << ends << (void*)&a << endl;

cin.get();

return 0;

}

运行

49ae0276ab622e3a034ae205b951945d.png

在函数fun内,对形参ra的值,做出了更改,这一操作影响了实参a。显然引用的使用比指针简单。

4.引用与数组

int a[]{1, 2, 3, 4, 5};

int (&ra)[5] = a;    //对数组进行引用

5.引用与指针

引用一级指针

int a(0), *p = &a;

int *&rp = p;

引用二级指针

int a(0), *p = &a;

int **pp = &p;

int **&rp = pp;  //引用二级指针,若编译不通过,使用 int (**(&rp)) = pp;

6.引用与函数指针

#include

using namespace std;

int add(int a, int b)

{

return a + b;

}

int sub(int a, int b)

{

return a - b;

}

int mul(int a, int b)

{

return a * b;

}

int divi(int a, int b)

{

if (b)

return a / b;

else

return INFINITY;

}

int main()

{

int a(100), b(10);

cout << "使用函数名" << endl;

cout << add(a, b) << ends << sub(a, b) << ends << mul(a, b) << ends << divi(a, b) << endl;

//padd是函数指针

int(*pfun)(int, int);

cout << "使用函数指针" << endl;

pfun = add;

cout << pfun(a, b) << ends;

pfun = sub;

cout << pfun(a, b) << ends;

pfun = mul;

cout << pfun(a, b) << ends;

pfun = divi;

cout << pfun(a, b) << endl;

//函数指针数组

int(*pfuns[])(int, int){add, sub, mul, divi};

cout << "使用函数指针数组" << endl;

cout << pfuns[0](a, b) << ends << pfuns[1](a, b) << ends << pfuns[2](a, b) << ends << pfuns[3](a, b) << endl;

cout << "函数指针的引用" << endl;

int(*(&rfun0))(int, int)(pfuns[0]);

int(*(&rfun1))(int, int)(pfuns[1]);

int(*(&rfun2))(int, int)(pfuns[2]);

int(*(&rfun3))(int, int)(pfuns[3]);

cout << rfun0(a, b) << ends << rfun1(a, b) << ends << rfun2(a, b) << ends << rfun3(a, b) << endl;

cin.get();

return 0;

}

运行

99ae0c88c8ac78fd94435d56a8815a25.png

------------------------------分割线------------------------------

将C语言梳理一下,分布在以下10个章节中:

0b1331709591d260c1c78e86d0c51c18.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值