你好,我是安然无虞。 |
文章目录
学习网站
推荐给老铁们两款学习网站:
面试利器&算法学习:牛客网 风趣幽默的学人工智能:人工智能学习 首个付费专栏:《C++入门核心技术》
写在前面
前面我们有讲解函数重载相关的知识,因为比较重要,所以讲的比较详细,下面还有一个很重要的知识点——引用,虽然很重要但是不难哦,不信你看看就知道了。
引用概念
引用不是新定义一个变量,而是给已存在变量取一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
比如:我们知道,在水浒传中有一个好汉名叫李逵,他在家呢叫“铁牛”,江湖人称“黑旋风”。
有点小可爱哦。
基本结构:
类型& 引用变量名 = 引用实体;
注意哦,引用类型必须是和引用实体是同种类型的。
看下面一段代码:
前面引用的概念已经说了,引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块空间。
这样的话也就是说,变量a、b、c、d共用同一块空间。
调试代码验证一下上面的说法,看四个变量的地址:
很明显地址一样,所以说,引用不是新定义一个变量,而是给已存在的变量取一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
引用特性
- 引用在定义时必须初始化;
- 一个变量可以有多个引用;
- 引用一旦引用一个实体,不能再引用其他实体。
对上述三个特性一一说明:
1.引用在定义时必须初始化
2.一个变量可以有多个引用
3.引用一旦引用一个实体,再不能引用其他实体(注意哦,这点跟指针不同)
常引用
开始之前呢,先说一下取别名的原则:
对原引用变量,读写权限要么不变,要么缩小,但是不能放大。
下面这段代码:
为什么加上const就可以了呢?
不着急,先说说之前学习过的知识。我们在学习C语言的时候知道不同类型的值相互赋值时会发生隐式类型的转换,比如:
很明显,发生隐式类型转换时中间会产生一个临时变量,而临时变量具有常性。
知道这一点上之后,就好解释这段代码了:
上面有说到rd不是d的别名,而是临时变量的别名,下面我们调试验证:
引用使用场景
· 做参数
之前我们写交换函数是这样写的:
现在我们学习引用后,大可不必像之前那样:
使用引用传参的好处:
- 无需解引用,简单多了;
- 使用引用传参更直观,更好理解。
· 做返回值
我们知道,传值返回时会有一个拷贝,而传引用返回就没有这个拷贝,返回的直接就是变量的别名,这样可以减少拷贝,提高效率。
思考下面一段代码:
传引用返回的是返回值的别名,传值返回的是那个临时变量。
所以这里返回的是n的别名,为了证明这个说法,只需要验证ret 和 n的地址一样,意味着ret 就是 n 的别名。
好,下面进行调试验证:
故而证明上述结论:
传引用返回的是返回值的别名,传值返回的是那个临时变量。
好的,现在将代码改动一点:
我们知道,传值返回的是那个临时变量,那么如何证明产生临时变量了呢?很简单,不信你看:
其实不难,不过需要你细品。
再看下面一段代码,问输出结果是什么?为什么?
其实这里的 Add 函数是错误的,因为 c 是局部变量,出了作用域就被销毁了,所以不能使用引用传参,会导致野指针。
注意:函数返回时,出了函数作用域,如果返回对象还未还给系统,则可以使用引用返回,如果已经还给系统了,则必须使用传值返回。
传值、传引用效率比较
以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。
引用和指针的区别
在语法概念上引用就是一个别名,没有独立的空间,和其引用的实体共用同一块空间。
不过在底层实现上其实是有空间的,因为引用是按照指针方式来实现的。看汇编代码即可证明:
我们来看一下引用和指针的汇编代码对比:
看到了吗,一模模一样!
总结引用和指针的不同点:
- 引用在定义时必须初始化,指针没有要求;
- 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型的实体;
- 没有NULL引用,但有NULL指针;
- 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台占4个字节,64位平台占8个字节);
- 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小;
- 有多级指针,但是没有多级引用;
- 访问实体方式不同,指针需要显示解引用,引用是编译器自己处理;
- 引用比指针使用起来相对更加安全。
上面这8点,不要死记硬背,要理解性记忆哦!
大厂面试真题
1、关于引用以下说法错误的是( )。(阿里)
A.引用必须初始化,指针不必
B.引用初始化以后不能被改变,指针可以改变所指的对象
C.不存在指向空值的引用,但是存在指向空值的指针
D.一个引用可以看作是某个变量的一个“别名”
E.引用传值,指针传地址
F.函数参数可以声明为引用或指针类型
解析:引用表面好像是传值,其本质也是传地址,只是这个工作有编译器来做,所以E错。
2、引用”与指针的区别是什么( )
A.指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作
B.引用通过某个引用变量指向一个对象后,对它所指向的变量间接操作。程序中使用引用,程序的可读性差;而指针本身就是目标变量的别名,对指针的操作就是对目标变量的操作
C.指针比引用更节省存储空间
D.以上都不正确
解析:指针是间接操作对象,引用时对象的别名,对别名的操作就是对真实对象的直接操作;指针需要开辟空间,引用不需要开辟空间。
3、关于引用与指针的区别,下面叙述错误的是( )
A.引用必须被初始化,指针不必
B.指针初始化以后不能被改变,引用可以改变所指的对象
C.删除空指针是无害的,不能删除引用
D.不存在指向空值的引用,但是存在指向空值的指针
解析:空指针没有任何指向,删除无害,引用是别名,删除引用就删除真实对象。
遇见安然遇见你,不负代码不负卿。 |