350 likes | 478 Views
第九章 引用. 9.1 引用的概念 9.2 引用的操作 9.3 什么能被引用 9.4 用引用传递函数参数 9.5 返回多个值. 引言. C++ 中包含了一个称为 引用 的特性,它允许程序来负责确定把参数传递给函数的方法。. 9.1 引用的概念. 定义 :引用是个别名,当建立引用时,程序用另一个变量或对象(目标)的名字初始化它。从那时起引用作为目标的别名而使用,对引用的改动实际就是对目标的改动。 格式 :为建立引用,先写上目标的类型,后跟引用运算符 “ & ” ,然后是引用的名字。引用能使用任何合法变量名。
E N D
第九章 引用 9.1 引用的概念 9.2 引用的操作 9.3 什么能被引用 9.4 用引用传递函数参数 9.5 返回多个值
引言 C++中包含了一个称为引用的特性,它允许程序来负责确定把参数传递给函数的方法。
9.1 引用的概念 定义:引用是个别名,当建立引用时,程序用另一个变量或对象(目标)的名字初始化它。从那时起引用作为目标的别名而使用,对引用的改动实际就是对目标的改动。 格式:为建立引用,先写上目标的类型,后跟引用运算符“&”,然后是引用的名字。引用能使用任何合法变量名。 补: 目标类型名 &引用名=目标变量名;
例:引用一个整形变量: int someInt; int &rInt=someInt; 注意: (1)引用不是值,不占存储空间,声明引用时,目标的存储状态不会改变。 (2)引用只有声明,没有定义。 (3)引用名用目标变量名来初始化。以后,无论改变目标变量名还是引用名,实际上都是指目标变量名,两者的值都一样。 (4)引用在声明时必须被初始化,否则会产生编译错误。
例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; }
9.1 引用的概念(续1) 例1: (续) 结果: intOne:5 rInt:5 intOne:7 rInt:7
补充:引用运算符与地址操作符的区别 引用运算符与地址操作符使用相同的符号。尽管它们彼此相关,但它们不一样。 (1)引用运算符只在声明的时候使用,它放在类型名后面。 例:int& rInt=intone; (2)任何其他“&”的使用都是地址操作符。 例:int *ip=&intone; cout<< &ip; (3)为了提高可读性,不应在同一行上同时声明引用、指针和变量。
第九章 引用 9.1 引用的概念 9.2 引用的操作 9.3 什么能被引用 9.4 用引用传递函数参数 9.5 返回多个值
9.2 引用的操作 如果程序寻找引用的地址,它只能找到所引用的目标的地址。
例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; }
9.2 引用的操作(续1) 例1: (续) 结果: intOne:5 rInt:5 &intOne:00F3:5300 &rInt:00F3:5300
9.2 引用的操作(续2) 说明: (1)C++没有提供访问引用本身地址的方法,因为它与指针或其他变量的地址不同,它没有任何意义。 (2)引用一旦初始化,它就维系在一定的目标上,再也不分开。
例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;
例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; }
例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
9.2 引用的操作(续3) 说明: (1)在程序中,引用rInt被重新赋值为变量intTwo。从运行结果看出,rInt仍然维系在原intOne上,因为rInt与intOne的地址是一样的。 (2)rInt=intTwo; 等价于intOne=intTwo; 小结:引用与指针有很大的差别,指针是个变量,可以把它再赋值成指向别处的地址,然而,建立引用时必须进行初始化并且决不会再关联其他不同的变量。
第九章 引用 9.1 引用的概念 9.2 引用的操作 9.3 什么能被引用 9.4 用引用传递函数参数 9.5 返回多个值
9.3 什么能被引用 若一个变量声明为T&,即引用时,它必须用T类型的变量或对象,或能够转换成T类型的对象进行初始化。 如果引用类型T的初始值不是一个左值,那么将建立一个T类型的目标并用初始值初始化,那个目标的地址变成引用的值。 例:下面的代码是合法的: double & rr=1;
9.3 什么能被引用(续1) 在这种情况下: (1)首先作必要的类型转换; (2)然后将结果置于临时变量; (3)最后,把临时变量的地址作为初始化的值。 所以上面的语句解释为: double temp; temp=double(1); double & rr=temp;
9.3 什么能被引用(续2) 说明: (1)上面的语句中临时变量显式地表示出来,事实上,临时变量并不在存放局部变量的栈区。 (2)由于指针也是变量。所以可以有指针变量的引用: int * a; int * &p=a; //表示int * 的引用p初始化为a int b=8; p=&b;
9.3 什么能被引用(续3) 注意: (1)对void 进行引用是不允许的。 (2)不能建立引用的数组。 (3)引用本身不是一种数据类型,所以没有引用的引用,也没有引用的指针。 (4)引用不能用类型来初始化。
第九章 引用 9.1 引用的概念 9.2 引用的操作 9.3 什么能被引用 9.4 用引用传递函数参数 9.5 返回多个值
9.4 用引用传递函数参数 主要内容: 1. 引用传递函数 2. 引用存在的问题
1.引用传递参数 传递引用给函数与传递指针的效果一样,传递的是原来的变量或对象,而不是在函数作为域内建立变量或对象的副本。
与指针的比较: (1)在8.6节中,看到对swap(int,int)传值方式函数的调用不影响调用函数中的实参,结果并未达到交换数据的预想目的; (2)使用指针传递方式的swap(int *,int *)函数的调用,能够达到预定的目的,但是函数的语法相对传值方式来说比较累赘。首先,在swap()函数内需要重复传递引用(dereference)(* px),这容易产生错误且难于阅读。其次,调用函数需要传递变量地址,使swap()内部的工作对用户太过显然。而且还有swap(&x,&y)的形式会造成一种交换两个变量地址的错觉。
例:用引用改写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; }
例:(续) 结果: before swap, x:5 ,y:6 after swap, x:6 ,y:5 说明: 在主函数中,调用swap()函数的参数是x和y,简单地传递变量而不是它们的地址。而事实上,传递的是它们的地址。引用传递的内存布局与指针相仿,只是操作完全不同。每当使用引用时,C++就去求该引用所含地址中的变量值。
1.引用传递参数(续1) 优点: 引用具有指针的威力,但是调用引用传递的函数时,可读性却比指针传递好。引用具有传值方式函数调用语句的简单性与可读性,但是威力却比传值方式强。
2.引用存在的问题 尽管引用可以表达清晰并让程序员负责了解如何传递参数,但是在有些情况下它们能隐藏错误。 例:下面的代码在没有看到函数原型之前可能会误认为实参a和b是通过值来传递的,从而不能通过函数调用来修改它,而事实上却能够修改: int a =10; int b =20; swap(a,b);
2.引用存在的问题(续1) 说明:因为引用隐藏了函数所使用的参数传递的类型,所以无法从所看到的函数调用判断其是值传递还是引用传递。
第九章 引用 9.1 引用的概念 9.2 引用的操作 9.3 什么能被引用 9.4 用引用传递函数参数 9.5 返回多个值
9.5 返回多个值 函数只能返回一个值。 如果程序需要从函数返回两个值怎么办?解决的办法之一是用引用给函数传递两个参数,然后由函数往目标中填入正确的值。因为用引用传递让函数改变原来的目标,这一方法实际上让函数返回两个信息。这一策略绕过了函数的返回值,使得可以把返回值保留给函数,作报告运行成败或错误原因用。 引用和指针都可以用来实现这一过程。
例:下面的程序实际上返回了三个值,两个是引用,另一个是函数返回值:例:下面的程序实际上返回了三个值,两个是引用,另一个是函数返回值: //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;} }
例: (续) 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
9.5 返回多个值(续1) 说明: Factor()函数检查用值传递的第一参数。如果不在0~20的范围内,它就简单的返回错误值(假设程序正常返回为0)。程序所真正需要的值squared和cubed是通过改变传递给函数的引用返回的,而没有使用函数返回机制。