(根据《C++程序设计》(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明)

对一个数据可以建立一个“引用”,它的作用是为一个变量起一个别名。这是C++对C的一个重要扩充。本系列分两篇,本篇为基础篇,主要是介绍基本知识。

1 基本概念及注意事项

1.1 引用概念

假如有一个变量a,想给它起一个别名b,可以这样写:

   1: int a ;

   2: int &b = a ; //声明b是a的“引用”

以上声明了b是a的引用,即b是a的别名。经过这样的声明后,使用a和b的作用相同,都代表同一个变量。注意:在上述声明中,&是引用声明符,并不代表地址。在数据类型名出现的&是引用声明符,在其他场合出现的都是取地址符。声明变量b为引用,并不需要另外开辟内存单元来存放b的值。b和a占内存中同一内存单元它们具有同一地址。即声明b是a的引用,可以理解为:使变量b具有变量a的地址。

1.2 注意事项

(1)引用不是一种独立的数据类型。对引用只有声明,没有定义。

    必须先定义一个变量,然后声明对该对象建立一个引用。关于定义和引用的具体区别,将会在近期的博客中整理。暂时可以简单的这样理解:变量定义,用于为变量分配存储空间,还可为变量指定初始值;变量声明,用于向程序表明变量的类型和名字。

(2)声明一个引用时,必须同时使之初始化,即声明它代表哪一个变量。

注意:当引用作为函数形参时不必在声明中初始化,它的初始化是在函数调用时的虚实结合实现的,即作为形参的引用是实参的别名。

(3)声明一个引用后,不能再使之作为另一个变量的引用。

比如声明了b是变量a的引用后,在其有效作用范围内,b始终与其代表的变量a联系,不能在作为其他变量的引用,例如下面的用法就不合法:

   1: int a1 ,a2 ;

   2: int &b = a1 ; //声明b是a1的引用

   3: int &b = a2 ; //试图使b又变成a2的引用,不合法

(4)不能建立引用数组。

下面的用法不合法:

   1: int a[5] ;

   2: int &b[5] = a ; //错误,不能建立引用数组

   3: int &b = a[0] ; //错误,不能建立数组元素的引用

(5)不能建立引用的引用。

下面的用法也不合法:

   1: int a = 3 ;

   2: int &b = a ; //声明b是a的引用,正确

   3: int &c = b ; //错误,试图建立引用的引用

2 引用的应用

唉?好奇怪啊,有了变量名,为什么还需要一个别名呢?C++之所以增加引用机制,主要一个方面就是把它作为函数的参数,以扩充函数传递数据的功能。闲话少说,上例子!

为了说明引用的作用,我们写函数实现两个数据值得交换。有人说这还不简单,信手拈来嘛:

   1: void swap (int a ,int b)

   2: {

   3:     int temp = a ;  

   4:     a = b ;

   5:     b = temp ;

   6: }

若在主函数中调用此函数,试图交换变量i和j的值:

   1: int i = 3 ;

   2: int j = 5 ;

   3: swap(i,j) ;

唉,好奇怪,怎么没有得到正确答案呢?这就要说道函数参数传递的机制了,这位同 学想通过改变形参的值,而改变实参的值,但是他用的函数参数传递机制却是:

(1) 将变量名作为实参和形参。

这时传给形参的是变量的值,传递是单向的.如果在执行函数期间形参的值发生变化,并不传回给实参.因为在函数调用时,形参和实参不是同一个存储单元。

那又有同学说了,那可以传递变量的地址啊,说着就写出了下述程序:

   1: void swap(int* p1 ,int* p2)

   2: {

   3:     int temp ;

   4:     temp = *p1 ;

   5:     *p1 = *p2 ;

   6:     *p2 = temp ;

   7: }

也在主函数中测试了一下:

   1: int i = 3 ;

   2: int j = 5 ;

   3: swap(&i,&j) ;

然后测试i,j的值,得到了正确答案。这位同学是利用了第二种参数传递的机制:

(2)传递变量的地址。

形参是指针变量,实参是一个变量的地址,调用函数时,形参(即指针变量)得到实参变量的地址,从而指向实参变量单元。调用函数时把变量i和j的地址传送给形参p1和p2 。所以p1就指向变量i,p2就指向j。通过交换指针所指的值,当然就交换了i和j 。这种方式通过形参变量指针访问主函数中的变量,并改变它们的值,虽然能得到正确结果,但是在概念上却是兜了一个圈子。下面就介绍第三种写法:

   1: void swap(int &a , int &b)

   2: {

   3:     int temp ;

   4:     temp = a ;

   5:     a = b ;

   6:     b = temp ;

   7: }

主函数中:

   1: int i = 3 ;
   2: int j = 5 ;
   3: swap(i,j) ;

也得到了正确结果。这里用到了第三种参数传递机制:

(3)以引用作为形参,在虚实结合中建立变量的引用,使形参名作为实参的引用,即形参称为实参的引用。

当main函数调用swap函数时,进行虚实结合,把实参变量i和j的地址传递给形参a和b,使a称为i的别名,b称为j的别名,当然a和b的值交换了,i和j的值也交换了。这就是地址传递方式。

那么这三种传递参数的方式有啥不同呢:

其实上述三种传递方式,可归纳为两种:传值方式和传址方式。

传值方式:(1)和(2)是传值方式,在(1)中,把变量i和j的值传递给形参a和b。在(2)中,把&i和&j的值传递给指针变量p1和p2 。在此方式中实参是地址(&i和&j),传递的是地址,故仍然是传值方式,不是传址方式。传值方式在调用函数时,需要对形参分配存储单元。

传址方式:(3)为此方式,实参不是地址而是变量名,由于形参是引用,系统会自动的将形参的地址传递给形参。注意:此时传送的是地址而不是实参变量的值。

总结一下:用引用形参的方法比使用指针简单、直观、方便,可以部分代替指针的操作。当然这只是引用的用处之一,引用的厉害指出多着呢,待后续娓娓道来。。。

最新文章

  1. LLBL Gen + Entity Framework 程序设计入门
  2. [转]Neural Networks, Manifolds, and Topology
  3. Android Memory Leak
  4. Winform控件缩写
  5. Windows8.1使用博客客户端写博客
  6. MySQL 索引的使用
  7. Jacobi symbol(裸雅可比符号)
  8. P1045 麦森数
  9. Mysql编译安装详解
  10. CentOS 显示历史执行过的命令以及用户历史命令缓存文件
  11. win10 远程出现身份验证错误 要求的函数不受支持
  12. 比较两种方式的form请求提交
  13. 拓展jquery js动态添加html代码 初始化数据
  14. Django-Filter源码解析一
  15. iOS 基于MVC设计模式的基类设计
  16. node(4)express 框架 EJS模板,cookie, session的学习
  17. python多线程练习
  18. 数论E - Biorhythms(中国剩余定理,一水)
  19. ubuntu安装Percona Server
  20. JNLP文件具体说明编辑

热门文章

  1. HDU 1969(二分法)
  2. Tomcat日志catalina.out文件过大的处理方法
  3. ViewPager,使用Fragment实现
  4. PHPExcel用法
  5. Week5(10月11日):国庆后补课的复杂心情
  6. 使用DiskGenius对虚拟机磁盘进行压缩
  7. 引用 移植Linux到s3c2410上
  8. Hdu 1158 Employment Planning(DP)
  9. Hadoop之——又一次格式化hdfs系统的方法
  10. Column store index 列数据如何匹配成行数据?