相信学过C++的同学都知道,引用是C++中的一个很强大的机制。我们在函数的传参,函数的返回值等等。当时我学引用的时候正赶上疫情…所以老师线上讲的可能不是那么透彻。好了,废话不多说,让我们来看一看引用到底是一个什么东东。
引例
想象一下,小时候和你住一个院儿里的有一个小朋友叫做,郝好笑。哈哈哈这个名字是不是贼有意思?她呢,特别幽默,所以院子里的小盆友给她起了个外号(别名)叫做开心果。久而久之,每次小朋友们去找郝好笑的时候,都会问她的家人一句:“阿姨,请问开心果在吗?”
这个例子不难理解吧。
其实我想表达的意思就是:引用就是一个别名,一个外号。但是你通过这个别名或者外号去指挥操纵被起别名的那个对象时,其实用真实名字来操纵的效果是一样的。(比如你问:“阿姨,请问郝好笑在吗?”)
光说不敲假把式,来段代码看看
#include <iostream>
using namespace std;
int main()
{
int a = 5;//L1
int &b = a;//L2
//int& c;错误,定义引用时必须赋初始值。//L3
b = 0;//L4
cout << "a=" << a << endl;//L5
}
输出结果:a = 0
L1:定义一位郝好笑小朋友
L2:起别名开心果
L3:想象一下,给一个不存在的人(对象)起别名,有意义吗?
L4:用别名操作对象
L5:通过这个别名或者外号去指挥操纵被起别名的那个对象时,其实用真实名字来操纵的效果是一样的。(a=0)
引用,顾名思义,就是"引"和"用"
int &b = a;"引"
b = 0;"用"
好了,通过上面这些,我们大概可以理解引用是什么东东了。但是你说引用占不占内存呢?
答案是肯定的:引用占4个字节,至于为什么我这就不讲了,大家可以搜搜它的底层实现原理之类的。
我此刻的目的只是初步理解它罢了。
拓展一下:
const与引用
先来看一段代码先:
int i = 9,
int& rr = i;
const int& ir = i;
rr = 8;
ir = 7; //错误,ir为const
大家应该可以看出rr与ir的区别吧
在定义引用时,可以用const来进行限制,使其变成一个不可以被修改的常量引用。
这个应该不难理解吧,const不就是常量的意思嘛
加上const与不加const有什么区别呢?
再来看一段代码
#include<iostream.h>
void main() {
int i = 10;
const double& x = 23 + 23 + i;
cout << "x=" << x << endl;
}
发现了吗,这里的引用居然不是用左值来初始化的。我们都知道引用一般必须用左值来初始化的,在这里居然可以用一个表达式来初始化一个引用。好神奇有没有!!
我来解释一下为什么
对于一个形如const T& x的初始化,则不必是一个左值,甚至可以不是T类型的,其处理过程度如下:
- 首先,如果需要,将应用T的类型转换。
- 而后将结果存入一个类型T的临时变量。
- 最后将此临时变量用作初始式的值
再来一道题吧
double dval = 1024;
const int& ri = dval;
dval = 90;
cout << "dval=" << dval << endl;
cout << "ri=" << ri << endl;
ri = 90; //错误,修改常量
问现在dval和ri的值分别是多少?
答案是dval=90; ri=1024;我想肯定有不少人感到奇怪。
引用不是一个人的别名吗,就想上面讲的例子似的,别名和真实姓名操作的肯定是同一个人啊!
这里我们同学们就要注意了。记得我刚才说的吗?将结果存入一个类型T的临时变量。最后将此临时变量用作初始式的值。
所以那个引用就不再是dval的别名了,而是在语句执行的那一刻dval的别名或者说是dval的在那一刻的一个分身。
本人水平有限,有什么不对的或者可以改进的,欢迎小伙伴的评论区里留言啊。