【C++养成计划】不得不知的——引用(Day9)

写在前面:大家好!我是【AI 菌】,一枚爱弹吉他的程序员。我热爱AI、热爱分享、热爱开源! 这博客是我对学习的一点总结与思考。如果您也对 深度学习、机器视觉、算法、Python、C++ 感兴趣,可以关注我的动态,我们一起学习,一起进步~
我的博客地址为:【AI 菌】的博客
我的Github项目地址是:【AI 菌】的Github

前言:
对于初学编程语言的同学来说,对于引用可能比较陌生,几乎用不到。但是在C++中,引用的地位就如同指针一样,它是你深入了解编程语言的必经之路,也是你提升代码质量的利器!那么今天我们就来聊聊C++中的引用吧~

想快速入门指针的同学,可以戳戳这篇有趣的分享:面试官:指针都不会,我们不需要你这样的人!

1. 什么是引用

在讲引用之前,我们得了解一个词——别名,也可以说是曾用名。想想自己从小到大,有过多少别名?
在这里插入图片描述
我们以猪八戒为例,它的别名就有很多个,比如:二师兄、悟净、天蓬元帅、八戒等等。了解了别名之后,其实你对引用就有了一个初步的认识!

简单来说,引用是变量的别名。变量,相信大家并不陌生,它是由变量名和变量值组成。那么当我们需要给变量取一个别名时,就可以使用引用。

在声明引用时,需要将其初始化为一个变量。因此通过引用,我们也可以访问该变量的数据。

在声明引用之前,我们需要了解一个符号:引用运算符 & 。通过&可以按如下方式进行声明:

声明引用:
Type 变量名 = 变量值;  //1.声明一个变量
Type& 别名 = 变量名;   //2.声明一个引用

下面举一个简单的例子,来感受一下:

#include <iostream>
using namespace std; 

int main()
{
	int a = 30;
	cout<<"a = "<<a<<endl;  
	cout<<"a的内存地址是:"<<hex<<&a<<endl;
	
	int& b = a;  //声明一个引用 ,b可作为s的别名 
	cout<<"b = "<<dec<<b<<endl;
	cout<<"b的内存地址是:"<<hex<<&b<<endl;
	
	int& c = b;  //声明一个引用,c可组为b的别名 
	cout<<"c = "<<dec<<c<<endl;
	cout<<"c的内存地址是:"<<hex<<&c<<endl; 
	return 0;
}

运行结果:
在这里插入图片描述
从上面这个例子,我们学习到了如何声明一个引用。更重要的是可以得出两条结论:

  1. 对于一个变量,可以声明多次引用;也就是说一个变量可以有多个别名,比如b、c都是a的别名。
  2. 引用不占用额外的内存空间。它的地址和原变量的地址相同,并且引用访问的值=原变量的值。比如a、b、c都是30,并且内存地址也相同。

注:程序中dec,是输出十进制的一种表示方法。

2. 按引用向函数传递参数

相信这个时候就有些同学坐不住了:什么?变量也需要别名?有什么用吗?
在这里插入图片描述
你别说,还真的很有用!

引用能让你访问相应变量所在的内存地址,这使得编写函数时引用很有用!

想想我们刚刚得出的一条结论:引用不占用额外的内存空间。这一点非常重要,这也是引用非常实用的原因。下面我们就来好好聊一聊:

回忆一下,在之前的【C++养成计划】深入浅出——函数(Day6)中讲过,在调用函数时,首先实参会被传给形参,然后再被函数使用。实参传递给形参,实质上是一个复制的过程;那么在这个过程中,无疑要给形参分配一个新的内存空间去存储实参传来的值。如果实参本身占用大量内存的话,这时复制的内存开销也会很大

如果能避免这些复制,那就能节省很多内存空间了。由于引用不占用额外的内存空间,并且它能让你访问相应变量所在的内存地址。因此这时候按引用向函数传递参数就可以大显神通了!

按引用向函数传递参数时,函数的声明方式像下面这样:

return_type func_name(type& Parameter);

由于实参是按引用传递的,因此实参不再是形参的拷贝,而是它的别名。下面举一个简单的例子:

#include <iostream>
using namespace std; 

void func(int& num)
{
	num = num*num*num;
}

int main()
{
	cout<<"请输入一个数:";
	int num = 0;
	cin>>num;
	func(num);
	cout<<"a="<<num<<endl;
	return 0;
}

运行结果:
在这里插入图片描述
想想,如果我们刚学函数,看到这个输出结果,肯定会感到很惊讶。因为我们学过:形参在进入函数时被创建,退出函数时被销毁。而在这个例子中,num并没有被销毁,并成功的输出了正确的结果。
这是因为,实参传递给形参时,是以引用的方式,而不是拷贝。所以函数在执行时,是直接对num所在的内存单元进行操作。因此即使函数结束,这个操作的结果依然存在。

3. 将关键字const用于引用

使用关键字const声明引用时,就不能通过引用修改它指向的变量的值了。

比如下面就是一个常见的错误:

int a = 30;
const int& b = a; //使用const声明一个静态引用
1.错误的做法:通过静态引用去修改变量
b = 40; //错误
2.正确的做法:通过原变量修改
a = 40; //正确
3.允许的做法:通过静态引用b再声明一个静态的引用
const int& c = b;

当按引用向函数传递参数时,为了确保被调函数不能修改调用函数中的变量,可将引用声明为const。
下面举一个简单的例子:使用const引用确保被调用函数不能修改num

#include <iostream>
using namespace std; 

void func(const int& num, int& result)
{
	result = num*num*num;
}

int main()
{
	int num = 2, output = 0;
	func(num, output);
	cout<<num<<"^3 = "<<output<<endl;
	return 0;
}

运行结果:
在这里插入图片描述
假如在被调用函数func()中,意外出现num=3这样的语句时:

void func(const int& num, int& result)
{
	num = 3;
	result = num*num*num;
}

程序就会编译不通过。这是因为num在函数声明时确定为const引用,所以在被调函数中,不能直接对num进行修改。这也保证了程序的安全性。


相关文章
点击查看【C++21天养成计划】

由于水平有限,博客中难免会有一些错误,有纰漏之处恳请各位大佬不吝赐教!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章