浅扒“引用 — &” -------- CPP

引用是CPP基于C语言的基础上提出的一个新的概念。本篇博客将和大家一起学习什么是引用,扒一扒引用的一些小细节,希望看完本篇博客后对你有所帮助。 

0b84bdb7c45e49d4a45858450a1482ed.png


一、引用的概念

引用不是定义一个新的变量,而是给已存在的变量取了一个别名,在语法上编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间

简单的说,引用就是给一个已存在的变量取一个别名

bbd8d64eb312450690380f08e5ecaa8e.gif

比如,我们称某知名练习生坤哥鸡哥只因哥,这些别名都指的是这个练习生

类型& 引用变量名(对象名) = 引用实体;

ae7e8c4f697c4296b770738d63b5a07b.png

void TestRef()
{
    int a = 10;
    int& ra = a;
    int& x = a;
    int& y = a;

    printf("%p\n", &a);
    printf("%p\n", &ra);
    printf("%p\n", &x);
    printf("%p\n", &y);
}

d40b08d34b1442dbbf60a2fe4ab72cb8.png

注意:引用类型必须和引用实体同种类型的。

引用的特性:

1. 引用在定义时必须初始化

bdcbc23532f249ffa00769b4e008623c.png

2. 一个变量可以有多个引用

int main()
{
    int a = 10;

    int& ra = a;
    int& x = a;
    int& y = a;

	return 0;
}

3. 引用一旦引用一个实体,再不能引用其他实体

二、引用的使用场景

2.1. 引用做函数形参

| 例 |

void Swap(const int& x, const int& y)    // x是实参a的别名,y是实参b的别名
{
	int tmp = x;    // 在函数中,x和y交换,main函数中的a和b也完成了交换
	x = y;
	y = tmp;
}

int main()
{
	int a = 1;
	int b = 2;

	Swap(a, b);
	printf("%d %d\n", a, b);

	return 0;
}

① 做输出型参数,在函数中修改形参,实参也修改了

② 减少拷贝,提高效率 (在传值传参中,形参是实参的一份临时拷贝,用引用做函数的形参,可以省去拷贝实参这一步,从而提高程序的效率)

2.2. 引用做返回值

| 传值返回 |

a535ad6685d9413fad831c629d794a02.png

| 引用返回 |

fa45ca623bda4860a23ee49dc22d01eb.png

由于引用返回的特性。如果Count函数中的n没有static修饰,此时系统为n在栈上开辟内存空间,当Count函数调用结束后,n的空间会还给操作系统。因为函数返回值的类型是引用类型,返回的是n的别名,通过返回的别名可以访问到系统先前为n开辟的那一块内存空间但这块内存空间已经还给系统了,所以这样的访问是不安全的

通过以上对引用类型的特性分析,我们可以得出一下结论:

● 如果出了函数作用域,返回的变量不存在了,则不能使用引用返回。因为引用返回的结果是未定义的。

● 如果出了函数作用域,返回的变量存在,则能使用引用返回。

| 附 |

一块内存空间的销毁意味着什么?

① 这块内存空间还存在吗?

      ● 存在,只是没有了该内存空间的使用权,先前存储在该内存空间中的数据不被保护了。

② 我们还能够访问这块内存空间吗?

      ● 能,只是我们读取的数据是不确定的。(再次访问该内存空间时,得到的数据可能是先前存放的数值,可能是随机值,也可能是被其他有意义的值所覆盖)

三、const修饰的引用类型

在学习const修饰的引用类型前,我们要先了解一条权限规则:在指针和引用的赋值中,权限可以被缩小,但是不能被放大。

77999a17a65d47158494e20a0a16a5b6.png

当函数中的形参是引用类型时,如果要缺省参数,则引用类型的参数要用const修饰。

8727f62267dd43c3b153d8e592e726d5.png

四、引用和指针的区别

语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。

底层实现上实际是有空间的,因为引用是按照指针方式来实现的

通过上面两句话好像并不能判断,这样说是否合理,还是要通过具体的实例来说明。

1d2e202ffcca4699ac4fbcbb68f73e67.png

 通过观察以上引用和指针的汇编代码对比,可以发现二者的汇编代码是一致的,由此可得出在底层实现上,引用是使用指针来实现的

引用和指针的不同点:

1. 引用在概念上是定义一个变量的别名,而指针则用来存储一个变量地址。

2. 引用在定义时必须初始化,指针则没有要求。

3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型的实体。

4. 没有NULL引用,但有NULL指针。

5. 在sizeof中含义不同sizeof(引用) 的结果为引用类型的大小,但 sizeof(指针) 则始终是地址空间所占字节个数。(32 位平台下占4个字节)

6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小。

7. 有多级指针,但是没有多级引用

8. 访问实体方式不同,指针需要显式解引用,而引用类型编译器会自己处理

9. 引用使用起来相对指针更安全。(使用指针可能会出现访问空指针和对野指针操作的问题,而引用则不存在此类问题)


本次与大家一起学习CPP中关于引用的内容到这就已经接近尾声了,期待下次与你相遇。

b8684054acbc4c178cabc301c68046bc.gif

< 你的关注点赞评论收藏都是对我创作最大的鼓励 > 

( 若本篇博客存在错误,望指出,感谢! )

  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 17
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值