关于引用的那些事

来源:互联网 发布:战略家炒股软件 编辑:程序博客网 时间:2024/06/06 09:24

刚开始接触c++,首先一定会了解引用,引用是c++扩展的一个变量类型,通俗点讲,就是变量的别名,与变量共享一块空间。有人可能会想,这很简单呀,不就是变量的别名吗?其实,引用最多的使用并不是作为变量的别名,而是作为函数的形参,可以实现通过函数调用来改变实参变量的值,怎么听起来这么熟悉呢,对了,你可能想起来通过指针也可以改变实参变量的值,那让我们来看看引用和指针有哪些联系和区别呢?

1.引用(reference):变量的别名。
对变量声明一个引用,并不另开辟内存单元,引用和变量代表同一变量单元。

注意:引用并不是定义一个新的变量,而是给已经定义的变量重新起一个别名。

2.引用定义的格式:
类型 &引用变量名 = 已定义过的变量名

3.引用的特点:
①一个变量可以取多个别名;
②引用必须初始化;
③引用只能在初始化的时候引用一次,不能再改变为引用其他的变量,也就是从一而终。

4.引用和指针的联系和区别:
①引用只能在定义时初始化一次,之后不能改变其指向其他变量(从一而终);指针可以改变其值
②引用必须指向有效的变量,指针可以为空。
③sizeof指针对象和sizeof引用对象的意义不同。sizeof指针对象:计算出的是对象地址的大小,而sizeof引用对象:对象的大小。
④指针和引用自增(++)自减(–)的意义不同。
⑤相对而言,引用比指针更安全。

其实,指针和引用在底层的实现是一样的,当引用作为函数形参时,其实传的也是引用变量的地址,和指针传值一样,只是指针传值时的实参是变量的地址,而引用就是引用变量,下面举例来看指针和引用传参时的底层实现。

1)指针作为形参

这里写图片描述

Test1的汇编代码:

这里写图片描述

2)引用作为形参:

这里写图片描述

Test1的汇编代码:

这里写图片描述

由上面的汇编代码可知,引用作为形参和指针和指针作为形参的参数传递底层实现是一样的。

5.引用需要注意的几个方面:
①不能建立void类型的引用。

②可以建立数组的引用
这里写图片描述

③可以用常量或者表达式对引用进行初始化,但必须是const引用。

这里写图片描述

包含隐式类型转换:
这里写图片描述

④用引用做返回值(重点分析):
例题1:
这里写图片描述

这里的结果你可以自己算一下,看是否和下面的结果是一样的?

这里写图片描述

如果不一样,没关系,下面我会解释为什么第二个值是随机值而第一个值是正确的?

解析:这时因为cout也是一个函数调用,所以也会生成栈帧,那么当add函数结束,栈帧销毁后,(栈帧销毁,只是将空间还给操作系统,但是里面的内容不会变化),第一个cout函数还可以输出正确的值,是因为ret所代表的那块空间的值还不变,调用函数先是传参,所以第一次传参正确,当第一个cout函数调用结束后,ret那块空间的值已被覆盖,所以当调用第二个cout函数传参时,ret那块空间的值被第一个cout函数的栈帧覆盖了,所以第二次传参时传的是一个随机值,所以第二次输出的h就是一个随机值。

这里写图片描述

add函数的汇编:

这里写图片描述

Test2函数的汇编:
这里写图片描述

当返回值不是引用时,注意add函数返回时的汇编代码与上面返回引用时的汇编代码的对比:

这里写图片描述

add函数的汇编代码:
这里写图片描述

由上面的汇编代码可以很明显的观察出返回引用和返回值的区别:
引用作为返回值时也类似于指针返回,返回的都是地址。
从概念上:引用没有定义变量,即就是没有开辟空间。
但是实际上在编译器的底层,和指针一样,定义了一个指针保存变量的地址。

结论:
1.不要返回一个临时变量的引用。
2.如果返回对象出了当前的函数还存在,那么最好使用引用,因为引用比指针更高效。

题外话:如果本文对你有一丢丢的帮助,那么将使我感到莫大的欣喜,由于能力有限,可能会有理解不到位,或者错误的地方,欢迎大家批评指正哦…

3 0
原创粉丝点击