第5课 - 引用的本质分析

一、引用的意义

  1. 引用作为变量别名而存在,因此在一些场合可以代替指针;
  2. 引用相对于指针来说具有更好的可读性和实用性;
  3. 函数中的引用形参不需要 进行初始化。
  4. 如下图1所示,可以看用引用作为形参的函数在使用时会方便很多,因为不用像指针那样需要取变量地址。

                                             第5课 - 引用的本质分析

                                                                                    图 1

二、特殊的应用

(1)const引用

在C++中可以声明const引用,语法形式:const Type& name = var;

const引用让变量拥有只读属性,不可通过引用改变变量值,但还是可以通过指针修改变量值。如下图2所示;

                                        第5课 - 引用的本质分析

                                                                        图2

(2)当使用常量对const引用进行初始化时,C++编译器会为常量值分配空间,并将引用名作为这段空间的别名;使用常量对const引用初始化后将生成一个只读变量。如下图3所示:

                                             第5课 - 引用的本质分析

                                                                       图3

三、引用的本质

  1. 引用在C++中的内部实现是一个指针常量;如图4所示;
  2. C++编译器在编译过程中用指针常量作为引用的内部实现,因此引用所占用的空间大小与指针相同。
  3. 从使用的角度,引用只是一个别名,C++为了实用性而隐藏了引用的存储空间这一细节。如图5的代码执行后的结果如图6所示;从执行的结果可看出引用所占用的空间大小与指针相同。

                                            第5课 - 引用的本质分析

                                                                                                     图5

                                            第5课 - 引用的本质分析

                                                                  图6

四、引用的意义

C++中的引用旨在大多数的情况下代替指针

功能性:可以满足多数需要使用指针的场合

安全性:可以避开由于指针操作不当而带来的内存错误

操作性:简单易用,又不失功能强大

五、函数返回引用

引用作为函数的返回值时,必须在定义函数时在函数名前加上“&”;用引用作为函数的返回值的好处是在内存中不产生返回值的副本。引用作为函数的返回值的几种情况如下图7所示:

                                            第5课 - 引用的本质分析

                                                                            图7

  1. 图7中的情况1,因为d是局部变量,那么它会在函数返回后被销毁,main()函数的a就会成为“无所指”的引用,程序会进入未知状态。
  2. 图7中的情况2,函数demo2()是以值方式返回到,返回时,首先拷贝temp的值给临时变量。返回到主函数后,用临时变量来初始化引用变量b,使得b成为该临时变量到的别名。由于临时变量的作用域短暂(在C++标准中,临时变量或对象的生命周期在一个完整的语句表达式结束后便宣告结束) ,所以b面临无效的危险,很有可能以后的值是个无法确定的值。
  3. 图7中的情况3,函数demo3()的返回值不产生副本,而是直接将全局变量temp返回给主函数,即主函数的赋值语句中的左值是直接从变量temp中拷贝而来(也就是说c只是变量temp的一个拷贝而非别名),这样就避免了临时变量的产生。尤其当变量temp是一个用户自定义的类的对象时,这样还避免了调用类中的拷贝构造函数在内存中创建临时对象的过程,提高了程序的时间和空间的使用效率。
  4. 图7中的情况4,函数demo4()中的静态变量是存在全局存储区的,所以和demo3()一样,同样可以提高了程序的时间和空间的使用效率。
  5. 不能返回函数内部通过new分配的内存的引用。虽然不存在局部变量的被动销毁问题,但如果被返回的函数的引用只是作为一个临时变量出现,而没有将其赋值给一个实际的变量,那么就可能造成这个引用所指向的空间(有new分配)无法释放的情况(由于没有具体的变量名,故无法用delete手动释放该内存),从而造成内存泄漏。因此应当避免这种情况的发生。
  6. 当返回类成员的引用时,最好是const引用。这样可以避免在无意的情况下破坏该类的成员。
  7. 当函数返回全局变量的引用时,可以 被作为赋值表达式的左值。