1 / 35

第九章 引用

第九章 引用. 9.1 引用的概念 9.2 引用的操作 9.3 什么能被引用 9.4 用引用传递函数参数 9.5 返回多个值. 引言. C++ 中包含了一个称为 引用 的特性,它允许程序来负责确定把参数传递给函数的方法。. 9.1 引用的概念. 定义 :引用是个别名,当建立引用时,程序用另一个变量或对象(目标)的名字初始化它。从那时起引用作为目标的别名而使用,对引用的改动实际就是对目标的改动。 格式 :为建立引用,先写上目标的类型,后跟引用运算符 “ & ” ,然后是引用的名字。引用能使用任何合法变量名。

keenan
Télécharger la présentation

第九章 引用

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第九章 引用 9.1 引用的概念 9.2 引用的操作 9.3 什么能被引用 9.4 用引用传递函数参数 9.5 返回多个值

  2. 引言 C++中包含了一个称为引用的特性,它允许程序来负责确定把参数传递给函数的方法。

  3. 9.1 引用的概念 定义:引用是个别名,当建立引用时,程序用另一个变量或对象(目标)的名字初始化它。从那时起引用作为目标的别名而使用,对引用的改动实际就是对目标的改动。 格式:为建立引用,先写上目标的类型,后跟引用运算符“&”,然后是引用的名字。引用能使用任何合法变量名。 补: 目标类型名 &引用名=目标变量名;

  4. 例:引用一个整形变量: int someInt; int &rInt=someInt; 注意: (1)引用不是值,不占存储空间,声明引用时,目标的存储状态不会改变。 (2)引用只有声明,没有定义。 (3)引用名用目标变量名来初始化。以后,无论改变目标变量名还是引用名,实际上都是指目标变量名,两者的值都一样。 (4)引用在声明时必须被初始化,否则会产生编译错误。

  5. 例1:建立和使用引用。 //ch9_1.cpp #include<iostream.h> void main() { int intOne; int &rInt=intOne; intOne=5; cout<<”intOne:”<<intOne<<endl; cout<<”rInt:”<<rInt<< endl; rInt=7; cout<<”intOne:”<<intOne<< endl; cout<<”rInt:”<<rInt<< endl; }

  6. 9.1 引用的概念(续1) 例1: (续) 结果: intOne:5 rInt:5 intOne:7 rInt:7

  7. 补充:引用运算符与地址操作符的区别 引用运算符与地址操作符使用相同的符号。尽管它们彼此相关,但它们不一样。 (1)引用运算符只在声明的时候使用,它放在类型名后面。 例:int& rInt=intone; (2)任何其他“&”的使用都是地址操作符。 例:int *ip=&intone; cout<< &ip; (3)为了提高可读性,不应在同一行上同时声明引用、指针和变量。

  8. 第九章 引用 9.1 引用的概念 9.2 引用的操作 9.3 什么能被引用 9.4 用引用传递函数参数 9.5 返回多个值

  9. 9.2 引用的操作 如果程序寻找引用的地址,它只能找到所引用的目标的地址。

  10. 例1:取引用的地址。 //ch9_2.cpp #include<iostream.h> void main() {int intOne; int &rInt=intOne; intOne=5; cout<<”intOne:”<<intOne<<endl; cout<<”rInt:”<<rInt<<endl; cout<<”&intOne:”<<&intOne<<endl; cout<<”&rInt:”<<&rInt<<endl; }

  11. 9.2 引用的操作(续1) 例1: (续) 结果: intOne:5 rInt:5 &intOne:00F3:5300 &rInt:00F3:5300

  12. 9.2 引用的操作(续2) 说明: (1)C++没有提供访问引用本身地址的方法,因为它与指针或其他变量的地址不同,它没有任何意义。 (2)引用一旦初始化,它就维系在一定的目标上,再也不分开。

  13. 例2:给引用赋新值。 //ch9_3.cpp #include<iostream.h> void main() {int intOne; int & rInt=intOne; intOne=5; cout<<”intOne:”<<intOne<<endl; cout<<”rInt:”<<rInt<<endl; cout<<”&intOne:”<<&intOne<<endl; cout<<”&rInt:”<<&rInt<<endl;

  14. 例2: (续1) int intTwo=8; rInt=intTwo; cout<<”intone:”<<intOne<<endl; cout<<”intTwo:”<<intTwo<<endl; cout<<”rInt:”<<rInt<<endl; cout<<”&intOne:”<<&intOne<<endl; cout<<”&intTwo:”<<&intTwo<<endl; cout<<”&rInt:”<<&rInt<<endl; }

  15. 例2: (续2) 结果: intOne:5 rInt:5 &intOne:0110:F150 &rInt:0110:F150 intOne:8 intTwo:8 rInt:8 &intOne:0110:F150 &intTwo:0110:F14E &rInt:0110:F150

  16. 9.2 引用的操作(续3) 说明: (1)在程序中,引用rInt被重新赋值为变量intTwo。从运行结果看出,rInt仍然维系在原intOne上,因为rInt与intOne的地址是一样的。 (2)rInt=intTwo; 等价于intOne=intTwo; 小结:引用与指针有很大的差别,指针是个变量,可以把它再赋值成指向别处的地址,然而,建立引用时必须进行初始化并且决不会再关联其他不同的变量。

  17. 第九章 引用 9.1 引用的概念 9.2 引用的操作 9.3 什么能被引用 9.4 用引用传递函数参数 9.5 返回多个值

  18. 9.3 什么能被引用 若一个变量声明为T&,即引用时,它必须用T类型的变量或对象,或能够转换成T类型的对象进行初始化。 如果引用类型T的初始值不是一个左值,那么将建立一个T类型的目标并用初始值初始化,那个目标的地址变成引用的值。 例:下面的代码是合法的: double & rr=1;

  19. 9.3 什么能被引用(续1) 在这种情况下: (1)首先作必要的类型转换; (2)然后将结果置于临时变量; (3)最后,把临时变量的地址作为初始化的值。 所以上面的语句解释为: double temp; temp=double(1); double & rr=temp;

  20. 9.3 什么能被引用(续2) 说明: (1)上面的语句中临时变量显式地表示出来,事实上,临时变量并不在存放局部变量的栈区。 (2)由于指针也是变量。所以可以有指针变量的引用: int * a; int * &p=a; //表示int * 的引用p初始化为a int b=8; p=&b;

  21. 9.3 什么能被引用(续3) 注意: (1)对void 进行引用是不允许的。 (2)不能建立引用的数组。 (3)引用本身不是一种数据类型,所以没有引用的引用,也没有引用的指针。 (4)引用不能用类型来初始化。

  22. 第九章 引用 9.1 引用的概念 9.2 引用的操作 9.3 什么能被引用 9.4 用引用传递函数参数 9.5 返回多个值

  23. 9.4 用引用传递函数参数 主要内容: 1. 引用传递函数 2. 引用存在的问题

  24. 1.引用传递参数 传递引用给函数与传递指针的效果一样,传递的是原来的变量或对象,而不是在函数作为域内建立变量或对象的副本。

  25. 与指针的比较: (1)在8.6节中,看到对swap(int,int)传值方式函数的调用不影响调用函数中的实参,结果并未达到交换数据的预想目的; (2)使用指针传递方式的swap(int *,int *)函数的调用,能够达到预定的目的,但是函数的语法相对传值方式来说比较累赘。首先,在swap()函数内需要重复传递引用(dereference)(* px),这容易产生错误且难于阅读。其次,调用函数需要传递变量地址,使swap()内部的工作对用户太过显然。而且还有swap(&x,&y)的形式会造成一种交换两个变量地址的错觉。

  26. 例:用引用改写swap()函数的定义及调用。 //ch9_4.cpp #include<iostream.h> void swap(int& rx,int& ry) ; void main() {int x=5; int y=6; cout<<”before swap,x:”<<x<<”,y:”<<y<<endl; swap(x,y); cout<<”after swap,x:”<<x<<”,y:”<<y<<endl; } void swap(int& rx,int& ry) //引用 {int temp; temp=rx; rx=ry; ry=temp; }

  27. 例:(续) 结果: before swap, x:5 ,y:6 after swap, x:6 ,y:5 说明: 在主函数中,调用swap()函数的参数是x和y,简单地传递变量而不是它们的地址。而事实上,传递的是它们的地址。引用传递的内存布局与指针相仿,只是操作完全不同。每当使用引用时,C++就去求该引用所含地址中的变量值。

  28. 1.引用传递参数(续1) 优点: 引用具有指针的威力,但是调用引用传递的函数时,可读性却比指针传递好。引用具有传值方式函数调用语句的简单性与可读性,但是威力却比传值方式强。

  29. 2.引用存在的问题 尽管引用可以表达清晰并让程序员负责了解如何传递参数,但是在有些情况下它们能隐藏错误。 例:下面的代码在没有看到函数原型之前可能会误认为实参a和b是通过值来传递的,从而不能通过函数调用来修改它,而事实上却能够修改: int a =10; int b =20; swap(a,b);

  30. 2.引用存在的问题(续1) 说明:因为引用隐藏了函数所使用的参数传递的类型,所以无法从所看到的函数调用判断其是值传递还是引用传递。

  31. 第九章 引用 9.1 引用的概念 9.2 引用的操作 9.3 什么能被引用 9.4 用引用传递函数参数 9.5 返回多个值

  32. 9.5 返回多个值 函数只能返回一个值。 如果程序需要从函数返回两个值怎么办?解决的办法之一是用引用给函数传递两个参数,然后由函数往目标中填入正确的值。因为用引用传递让函数改变原来的目标,这一方法实际上让函数返回两个信息。这一策略绕过了函数的返回值,使得可以把返回值保留给函数,作报告运行成败或错误原因用。 引用和指针都可以用来实现这一过程。

  33. 例:下面的程序实际上返回了三个值,两个是引用,另一个是函数返回值:例:下面的程序实际上返回了三个值,两个是引用,另一个是函数返回值: //ch9_5.cpp #include<iostream.h> int Factor(int, int& ,int&); void main() { int number,squared,cubed,error; cout<<”Enter a number(0~20):”; cin>>number; error=Factor(number,squared,cubed); if(error) cout<<”Error encountered! \n”; else {cout<<”Number:”<<number<<endl; cout<<”Squared:”<<squared<<endl; cout<<”Cubed:”<<cubed<<endl;} }

  34. 例: (续) int Factor(int n, int& rSquared, int& rCubed) { if(n>20|| n<0) return 1; rSquared = n*n; rCubed =n*n*n; return 0; } 结果: Enter a number(0~20):3 Number :3 Squared :9 Cubed :27

  35. 9.5 返回多个值(续1) 说明: Factor()函数检查用值传递的第一参数。如果不在0~20的范围内,它就简单的返回错误值(假设程序正常返回为0)。程序所真正需要的值squared和cubed是通过改变传递给函数的引用返回的,而没有使用函数返回机制。

More Related