《指针引用与动态内存分配.ppt》由会员分享,可在线阅读,更多相关《指针引用与动态内存分配.ppt(51页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配6.1 选择排序算法选择排序算法实现功能实现功能:将数组将数组listlist中的中的n n个数按照从大到小的顺序排个数按照从大到小的顺序排好之后再输出它们好之后再输出它们(此此n n个数通过使用函数个数通过使用函数randrand来自来自动产生动产生)。程序见程序见p6_1.cpp1第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配6.2 6.2 指针类型指针类型6.2.1 6.2.1 指针变量说明指针变量说明指针类型的变量说明格式为:指针类型的变量说明格式为:类型名类型名*指针变量名指针变量名=初值;初值;例如例如:
2、int i=3;:int i=3;int*pi;int*pi;/pi/pi为为int*int*型变量,其取值为一个型变量,其取值为一个intint型变量的型变量的地址,地址,/也称也称pipi为指向为指向intint型数据的指针变量(简称指型数据的指针变量(简称指针)针)2第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配pi=&i;pi=&i;/&/&作单目算符时为作单目算符时为“取变量地址取变量地址”,/此处将变量此处将变量i i的地址赋给指针变量的地址赋给指针变量pipicout*pi;cout*pi;/输出:输出:*pi*pi之值即之值即3 3/“*”/“*”作单目算符时为
3、作单目算符时为“取内容取内容”/(取指针所指向的那一变量的内容)(取指针所指向的那一变量的内容)*pi=123;*pi=123;/给给pipi所指向的那一变量,即所指向的那一变量,即i i,赋值,赋值123123/(等同于(等同于:i=123;:i=123;)3第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配说明:说明:类型名:类型名:任一基本类型名,基本类型的派生类型名,任一基本类型名,基本类型的派生类型名,用户定义的类用户定义的类枚举类型枚举类型结构类型结构类型联合类型名。联合类型名。类型名为类型名为void void 时,称为不确定类型的指针类型。时,称为不确定类型的指针类
4、型。类型名也可以是由类型名也可以是由类型名类型名*表示的指针类型名,表示的指针类型名,这时称为多级指针(指针类型的指针)。这时称为多级指针(指针类型的指针)。符号符号*:表示其后说明的变量为指针变量。表示其后说明的变量为指针变量。指针变量名:指针变量名:标识符。标识符。初值:初值:可缺省。它可以是该类型的某一变量的地址。可缺省。它可以是该类型的某一变量的地址。4第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配一个指针变量,可有三种状态:一个指针变量,可有三种状态:(1 1)未赋任何值,未赋任何值,“悬空悬空”状态。状态。(2 2)被赋予被赋予NULL NULL 值。未指向任一变量
5、。值。未指向任一变量。(3 3)指向某一变量。指向某一变量。注:规定注:规定NULL NULL 与整数与整数0 0 通用,它是唯一可以赋通用,它是唯一可以赋给任一类型指针变量的值。给任一类型指针变量的值。5第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配6.2.2 6.2.2 指针变量的操作指针变量的操作1.1.取地址运算取地址运算&和取内容运算和取内容运算*注意如下注意如下3 3处出现的处出现的*pi*pi,它们的含义不相同:,它们的含义不相同:int i=23,*pi=&i;int i=23,*pi=&i;cout*pi;cout*pi;*pi=56;*pi=56;6第六章第
6、六章 指针,引用与动态内存分配指针,引用与动态内存分配第第一一行行的的“*pi”“*pi”处处于于变变量量说说明明处处,是是说说明明pipi为为“int*”“int*”型型变变量量,并并同同时时将将该该指指针针变变量量初初始始化化为为i i的的地地址址。不不可可将将此此处处的的“*”“*”理理解解为为“取取内内容容”运运算算,它与前面的它与前面的intint联合起来以说明联合起来以说明pipi为为“int*”“int*”型变量。型变量。第第二二行行的的“*pi”“*pi”表表示示指指针针变变量量pipi所所指指向向的的那那一一变变量量(即即i i)的的内内容容(*理理解解为为“取取内内容容”运
7、运算算,使使用其值)。用其值)。第第三三行行的的“*pi”“*pi”为为左左值值(存存储储空空间间概概念念),表表示示要要改改变变指指针针变变量量pipi所所指指向向的的那那一一变变量量(即即i i)空空间间中的内容(使用其存储空间)。中的内容(使用其存储空间)。7第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配2.2.数组指针的算术运算数组指针的算术运算1)1)若若p p为指针,已指向数组的某一元素,为指针,已指向数组的某一元素,则则p+i(p+i(或或p-i,p-i,其中其中i i为正整数为正整数)也为一指针,也为一指针,它指向当前它指向当前p p已指元素的后面已指元素的后面
8、(或前面或前面)第第i i个元素。个元素。例例1 1:int a10;int a10;/任一数组名字任一数组名字a a都是一个常量指针都是一个常量指针,/代表数组的首地址代表数组的首地址,也即也即,a,a总等同于总等同于&a0&a08第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配则则,无无论论何何时时,下下述述两两种种表表示示数数组组元元素素aiai的的方方式总是相同的:式总是相同的:a0 *a a0 *a a1 *(a+1)a1 *(a+1).a9 *(a+9)a9 *(a+9)另另,下下述述两两种种表表示示数数组组元元素素aiai之之地地址址的的方方式式也也总是相同的:总是
9、相同的:&a0 a&a0 a&a1 a+1&a1 a+1.&a9 a+9&a9 a+9 9第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配例例2 2:int a10;int a10;int*pa=a;int*pa=a;/pa /pa为变量指针,此时为变量指针,此时papa与与a a /均指向数组均指向数组a a的首元素的首元素 则则,下下述述三三种种表表示示数数组组元元素素aiai的的方方式式是是等等同同的:的:a0 *a *paa0 *a *paa1 *(a+1)*(pa+1)a1 *(a+1)*(pa+1).a9 *(a+9)*(pa+9)a9 *(a+9)*(pa+9)10
10、第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配 另另,下下述述三三种种表表示示数数组组元元素素aiai之之地地址址的的方方式式也也是等同的:是等同的:&a0 a pa&a0 a pa&a1 a+1 pa+1&a1 a+1 pa+1.&a9 a+9 pa+9&a9 a+9 pa+9 而而 pa+=3;pa+=3;及及 pa-;pa-;也也都都为为正正确确的的句句子子(但但,a+=3;a+=3;及及 a-;a-;却都是不正确的句子却都是不正确的句子!为什么为什么?)?)。11第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配 另另外外需需注注意意的的是是:papa是是变
11、变量量,它它当当前前所所指指的的元元素素可可以以随随时时变变化化,从从而而pa+1,pa+pa+1,pa+等等语语句句所所指指向向的的元元素素也也跟跟着着变变化化。换换句句话话说说,使使用用指指针针变变量量去去访访问问数数组组元元素素时时,应应随随时时检检查查指指针针变变量量当当前前所所指指向向的的数组元素。数组元素。指指针针变变量量也也可可以以指指向向二二维维、三三维维等等多多维维数数组组元元素,例如:二维数组素,例如:二维数组 int a34 int a34的存储结构为:的存储结构为:a0a00a01a02a03a1a10a11a12a13a2a20a21a22a2312第六章第六章 指针
12、,引用与动态内存分配指针,引用与动态内存分配2)2)若若p,qp,q都为同类型的指针都为同类型的指针,则则p-qp-q为为p p与与q q之之间的数据项数间的数据项数(当当p,qp,q指向同一数组时指向同一数组时,结果结果有意义有意义)。3.3.指针的关系运算指针的关系运算指针变量可以参加关系运算。这要分三种情况:指针变量可以参加关系运算。这要分三种情况:(1 1)一般指针可以进行相等和不等的比较,指向)一般指针可以进行相等和不等的比较,指向同一变量(地址)者为相等,否则不等。同一变量(地址)者为相等,否则不等。(2 2)任一指针可以和指针常量)任一指针可以和指针常量NULL NULL 进行相
13、等和不进行相等和不等的比较。如一指针等的比较。如一指针p p 已经指向了某变量,则它不已经指向了某变量,则它不等于等于NULLNULL。13第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配(3 3)数组指针,可以指向该数组的各个元素,且)数组指针,可以指向该数组的各个元素,且一个数组的各个元素在内存中是顺序存放的,故数一个数组的各个元素在内存中是顺序存放的,故数组指针之间不但可以进行相等和不等比较,也可以组指针之间不但可以进行相等和不等比较,也可以进行大于,小于,大于等于,小于等于等的比较。进行大于,小于,大于等于,小于等于等的比较。14第六章第六章 指针,引用与动态内存分配指针
14、,引用与动态内存分配6.2.3 6.2.3 指针与数组指针与数组1 1指向数组元素的指针指向数组元素的指针2 2指向数组的指针指向数组的指针把数组作为整体,称为指向数组的指针,对于这类指针,把数组作为整体,称为指向数组的指针,对于这类指针,其说明语句格式为:其说明语句格式为:类型名(类型名(*指针变量名)指针变量名)数组元素数数组元素数;而指向多维数组的指针说明中,最后一项而指向多维数组的指针说明中,最后一项 数组元素数组元素数数 可有多个。可有多个。指向数组的指针又叫行指针,指向数组元素的指针又叫指向数组的指针又叫行指针,指向数组元素的指针又叫列指针。列指针。15第六章第六章 指针,引用与动
15、态内存分配指针,引用与动态内存分配例如:例如:int A34,int A34,(*pa*pa)44;pa=A pa=A;表示指针变量表示指针变量pa pa 是一个指向一维整型数组的指针,是一个指向一维整型数组的指针,该数组包含四个整型元素。该数组包含四个整型元素。执行增量运算执行增量运算pa+pa+;后,;后,pa pa 指向一维数组指向一维数组A1A1,数,数组组A1A1的四个元素是的四个元素是A10A10,A11A11,A12A12,A13A13。它们也可表示为(它们也可表示为(*pa*pa)00,(,(*pa*pa)11,(*pa*pa)22,(,(*pa*pa)33。16第六章第六章
16、指针,引用与动态内存分配指针,引用与动态内存分配例如:例如:float*P=&A00float*P=&A00;floatfloat(*pa*pa)44;pa=Apa=A;则:则:P+P+后,后,P P指向指向A01A01,*P*P是是A01A01的值;的值;pa+pa+后,后,papa指向指向A1A1即即A10A10,*pa*pa是地址是地址(列地址),(列地址),*pa*pa才是才是A10A10的值。的值。17第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配表示形式含义地址a数组首地址即0行首地址2000a0,*(a+0),*a 第0行0列元素地址2000a+1,&a1第1行首
17、地址2008a1,*(a+1)第1行0列元素地址2008a1+2,*(a+1)+2,&a12第1行第2列元素地址2012*(a1+2),*(*(a+1)+2),(*(a+1)2,a12第1行第2列元素的值元素值例:对二维数组例:对二维数组int a34int a34;地址与元素的表示如下:;地址与元素的表示如下:18第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配3 3指针数组指针数组由指针组成的数组,其说明格式为:由指针组成的数组,其说明格式为:类型名类型名*数组名数组名 元素数元素数(1)它比一般数组增加了符号*。(2)它比指向数组的指针,少了一对括号“()”例:例:int*
18、p;int*p12int*p;int*p12;intint(*p2*p2)44;p p 是指向是指向int int 型变量的指针,型变量的指针,p1 p1 是由两个整型指针是由两个整型指针组成的指针数组,而组成的指针数组,而p2p2则是一个指向一维整型数组的则是一个指向一维整型数组的指针。指针。19第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配4.4.指向指针的指针指向指针的指针例例:int x,*p,*q;int x,*p,*q;/q/q为指向指针的指针为指向指针的指针x=123;x=123;p=&x;p=&x;q=&p;q=&p;coutx=xendl;coutx=xend
19、l;cout*p=*pendl;cout*p=*pendl;cout*q=*qendl;cout*q=*qendl;/x,*p,*q/x,*p,*q之值均为之值均为12312320第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配若指向指针的指针变量p指向指针数组name首地址,则p+i指向namei即是namei的地址。pi*(p+i):是namei的值,还是地址,是namei指向的目的变量(数组)的地址(首地址)*(p+i):是namei指向的目的变量(数组)的值(第0号元素的值)pij*(*(p+i)+j)(*(p+i)j:是namei指向的一维数组的第j号元素的值,总之,p
20、的地位相当于name,类似于二维数组的首地址。21第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配6.2.4 6.2.4 字符串指针字符串指针 字符串是一种特殊的数据形式,它实际上是一字符串是一种特殊的数据形式,它实际上是一维字符数组。维字符数组。C+C+语言对于字符串的操作提供了多语言对于字符串的操作提供了多种手段,其中利用字符串指针是最方便的一种。种手段,其中利用字符串指针是最方便的一种。说明与初始化说明与初始化 字符串指针没有自己独立的形式,其说明语字符串指针没有自己独立的形式,其说明语句的格式与字符类型指针相同。句的格式与字符类型指针相同。22第六章第六章 指针,引用与动
21、态内存分配指针,引用与动态内存分配例如:例如:char ch=achar ch=a:char*pc1=&chchar*pc1=&ch;char*pc2=“world”char*pc2=“world”;/pc2/pc2是指针变量是指针变量char as10=“Chinese”char as10=“Chinese”;/as/as是数组名,是指针常是数组名,是指针常量量char*pc3=aschar*pc3=as;字符串指针可以按一般字符指针的规则工作;字符串指针可以按一般字符指针的规则工作;字符串指针有时可以按不同于一般指针变量的方式操字符串指针有时可以按不同于一般指针变量的方式操作,即有时它可以
22、表示字符串整体,而不是单单表示作,即有时它可以表示字符串整体,而不是单单表示当前指向的那个字符。当前指向的那个字符。23第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配 字符串的整体输入输出字符串的整体输入输出 把字符串作为字符数组,然后按字符依次进行输把字符串作为字符数组,然后按字符依次进行输入输出是可行的,但比较麻烦。因此,入输出是可行的,但比较麻烦。因此,C C语言再提供语言再提供整体输入输出的方法。整体输入输出的方法。把字符串变量用字符数组或字符串指针的形式表把字符串变量用字符数组或字符串指针的形式表示,然后直接进行示,然后直接进行I/O 操作:操作:cin字符串;字符串
23、;cout字符串;字符串;这里的字符串可以用字符串指针这里的字符串可以用字符串指针pc2,pc3 或字或字符数组名符数组名as 来表示,来表示,24第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配例如:例如:char as 10=world;char*pc2world;char*pc3=as;coutas;coutpc2;coutpc3;coutworld;后四个输出语句产生相同效果,都是输出了字符串后四个输出语句产生相同效果,都是输出了字符串world。25第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配char str 20;char*pc2=new char2
24、0;char*pc3=str;cinstr;cinpc2;cinpc3;后三个输入语句允许输入长度不超过后三个输入语句允许输入长度不超过20 的字符串,的字符串,忽略前导空格,以空格作为串尾。忽略前导空格,以空格作为串尾。26第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配 字符串指针数组字符串指针数组以字符串指针组成的数组使用起来比较方便,以字符串指针组成的数组使用起来比较方便,例如:例如:char*menu File,Edit,Search,Help;就是一个字符串指针数组,它的每个元素指向一个就是一个字符串指针数组,它的每个元素指向一个字符串常量。于是字符串常量。于是men
25、u0,menu1,menu2,menu3将分别表示将分别表示“File”,“Edit”,“Search”,“He1p”27第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配例:按人名字典序排列名表例:按人名字典序排列名表程序见程序见p6_4.cpp28第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配4利用字符串指针的标准函数利用字符串指针的标准函数在头文件string.h 中,C系统提供若干串处理函数:(1)求字符串长度。unsigned strlen(const char*str);返回字符串str 的长度(不包括串尾符)。(2)字符串拷贝:char*strcpy(
26、char*str1,char*str2);把字符串str2 拷贝给字符串strl(覆盖原来内容),返回strl 的地址。(3)字符串连接:char*strcat(char*str1,char*str2);把字符串str2 连接到字符串str1 的后面(使str1 加长),返回str1 的地址。(4)字符串比较:int strcmp(char*str1,char*str2);29第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配6.2.5 6.2.5 指针与函数指针与函数1指针作函数参数指针作函数参数 指针作函数的参数可以起到其它类型参数所起指针作函数的参数可以起到其它类型参数所起不
27、到的作用(实现双向传值)。不到的作用(实现双向传值)。void swap(float*pa,float*pb)float t=*pa;*pa=*pb;*pb=t;;void swap(float pa,float pb)float t=pa;pa=pb;pb=t;;注意:并非只要使用指针作函数的参数就可实现双向传值。注意:并非只要使用指针作函数的参数就可实现双向传值。30第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配2返回指针的函数返回指针的函数说明格式说明格式:*(););例:例:int*f();int*f();/f /f为无参函数,其返回值类型为无参函数,其返回值类型 /为
28、为int*int*,即指针类型。,即指针类型。char*match(char c,char*str);char*match(char c,char*str);/match/match为具有两个参数的函数,为具有两个参数的函数,/其返回值类型为其返回值类型为char*char*,即指针类型。,即指针类型。返回值为指针的函数称为指针型函数。返回值为指针的函数称为指针型函数。31第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配 下述示例性程序使用了返回指针值的自定义函下述示例性程序使用了返回指针值的自定义函数,实现如下功能:数,实现如下功能:提示用户输入任意一个字符串,而后找到输提示用
29、户输入任意一个字符串,而后找到输入串中第一个入串中第一个aa字符出现的位置字符出现的位置(若有的话若有的话),并输,并输出从出从aa字符开始的子串字符开始的子串;若输入串中不出现若输入串中不出现aa字字符的话符的话,输出输出“No match found”“No match found”。程序见程序见p6_2.cpp32第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配3指向函数的指针变量指向函数的指针变量 函数不是数据,但它与变量还是有两点相通之处:函数不是数据,但它与变量还是有两点相通之处:一个是它有类型(返回类型),另一个是它也有地址,一个是它有类型(返回类型),另一个是它也
30、有地址,称为入口地址,故在有的书中也勉强地把函数仍归为称为入口地址,故在有的书中也勉强地把函数仍归为一种特殊的数据一种特殊的数据“类型类型”。函数的地址也可作指针的值,这就是函数指针函数的地址也可作指针的值,这就是函数指针。指向函数的指针变量的说明格式指向函数的指针变量的说明格式:(*(*指针变量名指针变量名)()(参数表参数表););33第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配例如:例如:int(*pf)()(float););其中其中pf 是一个函数指针变量,由于对是一个函数指针变量,由于对pf 的说明中已规的说明中已规定了函数的返回类型(有时还包括存储类型)和参数表
31、,定了函数的返回类型(有时还包括存储类型)和参数表,因此,指针因此,指针pf 只能够指向这类函数。例如:只能够指向这类函数。例如:int f1(float);int f2(char);int f3(float);int f4(float);这时,下面的说明和赋值,就有合法与不合法的区别:这时,下面的说明和赋值,就有合法与不合法的区别:int(*pf)()(float)=&f1;/合法合法int(*pf1)()(char)=&f1;/不合法不合法pf=&f4;/合法合法pf=&f2;/不合法不合法pf=&f3;/合法合法注:加不加注:加不加&均可均可34第六章第六章 指针,引用与动态内存分配指针
32、,引用与动态内存分配 下述示例性程序通过使用指向函数的指针变下述示例性程序通过使用指向函数的指针变量来调用自定义函数量来调用自定义函数maxmax及及minmin。程序见程序见p6_3.cpp C C语言本身不允许把函数作为参数,然而有语言本身不允许把函数作为参数,然而有了函数指针,就可以通过函数指针,起到把函数作了函数指针,就可以通过函数指针,起到把函数作为参数的作用。为参数的作用。如:如:float simpson(float a,float,b,float(*pf)(float)35第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配注意区分注意区分:按照如下:按照如下9 9种
33、方式所定义的具有不同含义种方式所定义的具有不同含义的的a a。(1)(1)int a;int a;(2)(2)int*a;int*a;(3)(3)int*a;int*a;(4)(4)int a10;int a10;(5)(5)int*a10;int*a10;(6)(6)int(*a)10;int(*a)10;(7)(7)int a();int a();(8)(8)int*a();int*a();(9)(9)int(*a)();int(*a)();36第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配6.3 指针与动态内存分配指针与动态内存分配 通过使用通过使用newnew与与del
34、etedelete单目运算符来实现动态变单目运算符来实现动态变量的分配与撤消。量的分配与撤消。1)new 1)new 使用格式使用格式:new new /动态变量动态变量 new new ()new new /动态数组动态数组 功能功能:生成一个生成一个(或一批或一批)所给类型的无名动态变量所给类型的无名动态变量,返返回所生成变量的指针值回所生成变量的指针值(首地址首地址)。37第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配例:例:int*pi,*pj,a=10;int*pi,*pj,a=10;char*pc;char*pc;pi=new int;pi=new int;*pi=
35、a*a;*pi=a*a;pc=new char(A);pc=new char(A);pj=new int10;pj=new int10;38第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配2)delete2)delete 使用格式使用格式:delete delete delete delete 功能功能:释放通过释放通过newnew生成的动态变量生成的动态变量(或动态数组或动态数组),但指针变量仍存在。,但指针变量仍存在。39第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配例:例:int*pi,*pj;int*pi,*pj;pi=new int;pi=new int
36、;pj=new int10;pj=new int10;.delete pi;delete pi;/释放动态变量释放动态变量*pi,*pi,但指针变量但指针变量pipi仍仍存在存在 delete pj;delete pj;40第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配3)3)使用示例使用示例1.1.从键盘输入从键盘输入1010个个intint型数,而后按输入的相型数,而后按输入的相反顺序输出它们。要求使用反顺序输出它们。要求使用newnew运算符动态申运算符动态申请数据空间存放数据。请数据空间存放数据。程序见程序见p6_5.cpp注:在使用动态变量时,要注意保护动态变量的地注
37、:在使用动态变量时,要注意保护动态变量的地址,不要轻易地冲掉保存动态变量地址的指针变量址,不要轻易地冲掉保存动态变量地址的指针变量的值,否则动态变量将丢失。的值,否则动态变量将丢失。2.2.构建人员档案链表构建人员档案链表程序见程序见p6_8.cpp41第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配6.4 引用类型引用类型 简单的说,引用是某个变量或对象的别名。简单的说,引用是某个变量或对象的别名。建立引用时,必须用某个变量名或对象名来对建立引用时,必须用某个变量名或对象名来对它进行初始化,从而将该引用绑定在那一个变它进行初始化,从而将该引用绑定在那一个变量或对象上。量或对象上
38、。即是说,建立引用并不重新为其分配内存即是说,建立引用并不重新为其分配内存空间,引用只是另一变量或对象的别名,任何空间,引用只是另一变量或对象的别名,任何对引用的使用与改变都是对该引用所绑定的那对引用的使用与改变都是对该引用所绑定的那一变量或对象的使用与改变。一变量或对象的使用与改变。42第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配1.1.引用的建立引用的建立 建立引用的格式如下:建立引用的格式如下:&=例如例如:int a=2,b;int a=2,b;int&refa=a;/int&refa=a;/引用引用refarefa是是intint型变量型变量a a的别名的别名int
39、&refb=b;/int&refb=b;/引用引用refbrefb是是intint型变量型变量b b的别名的别名 那那么么经经赋赋值值“refb=55;”“refb=55;”以以及及“refa+=2;”“refa+=2;”之之后后,b b与与refbrefb的的当当前前值值都都将将是是5555,而而a a与与refarefa都都在在原原有值有值2 2的基础上增加了的基础上增加了2 2,即当前值都变成了,即当前值都变成了4 4。43第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配2.2.引用和指针的区别引用和指针的区别 引引用用和和指指针针从从说说明明到到使使用用上上都都有有些些相
40、相似似,但但在在概概念上却有着明显的不同。主要区别在以下几个方面。念上却有着明显的不同。主要区别在以下几个方面。(1)(1)指指针针表表示示的的是是一一个个对对象象变变量量的的地地址址,而而引引用用则则表表示示一一个个对对象象变变量量的的别别名名。因因此此在在程程序序中中表表示示其其对对象象变变量量时时,前前者者要要通通过过取取内内容容运运算算符符“*”“*”,而而后后者者可可直接代表。例如:直接代表。例如:int a;int a;int*pa=&a;int&ra=a;int*pa=&a;int&ra=a;当要对当要对a a赋值赋值123123时,下述三个语句是等价的:时,下述三个语句是等价的
41、:a=123;a=123;*pa=123;*pa=123;ra=123;ra=123;44第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配 (2)(2)指指针针是是可可变变的的,它它可可以以指指向向变变量量a a,也也可可以以指指向向变变量量b b,而而引引用用则则只只能能在在建建立立时时一一次次确确定定(固固定定绑定在某一个变量上),不可改变。例如:绑定在某一个变量上),不可改变。例如:int a,b=456;int a,b=456;int*p=&a;int*p=&a;int&ra=a;int&ra=a;以以后后再再执执行行“p=&b;”“p=&b;”是是合合法法的的,它它使使
42、指指针针p p又又改改指指变变量量b b。但但不不能能通通过过“ra=b;”“ra=b;”的的赋赋值值或或“int“int&ra=b;”&ra=b;”的的重重新新建建立立新新的的绑绑定定关关系系来来改改变变引引用用rara。前前者者的的“ra=b;”“ra=b;”的的赋赋值值只只是是将将b b的的值值(即即456456)赋赋给给了了与与rara绑绑定定的的变变量量a a;而而后后者者试试图图为为引引用用rara重重新新建建立立新新的的绑绑定定关关系系则则会会导导致致出出现现一一个个编编译译错错误误(rara重重定定义义,重复初始化)。重复初始化)。45第六章第六章 指针,引用与动态内存分配指针
43、,引用与动态内存分配 (3)(3)由由于于引引用用本本身身不不是是一一个个独独立立的的变变量量(它它本本身身不不具具有有独独立立的的变变量量地地址址,使使用用的的是是与与其其绑绑定定的的那那一一变变量量的的地地址址),所所以以,不不能能出出现现引引用用的的引引用用,不不能能出出现现元元素素为为引引用用的的数数组组,也也不不能能使使用用指指向向引引用用的的指指针针(注注意意,可可以以出出现现指指针针的的指指针针、可可以以出出现现元元素素为为指指针针的的数数组组,也也可可以以说说明明对对指指针针的的引引用用,这这都都缘缘于于指指针针是是独独立立变量的缘故)。变量的缘故)。int&ref;int&r
44、ef;/ERR!/ERR!不能出现引用的引用不能出现引用的引用int&refa10;int&refa10;/ERR!/ERR!不能出现元素为引用的数组不能出现元素为引用的数组int&*refp;int&*refp;/ERR!/ERR!不能使用指向引用的指针不能使用指向引用的指针int*pi,*&pref=pi;/OK!int*pi,*&pref=pi;/OK!可以说明对指针的引用可以说明对指针的引用 /将引用将引用prefpref与与int*int*类型的指针变量类型的指针变量pipi进行了绑定进行了绑定46第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配3.3.引用型参数引用型
45、参数 以以“&”&”形形式式说说明明的的函函数数参参数数,可可实实现现“双双向向传传值值”(被被调调函函数数中中对对形形参参值值的的使使用用与与改改变变,就就是是对对主主调调函函数数中中调调用用语语句句处处所所对对应应实实参参变变量量值值的的直直接使用与改变)。接使用与改变)。可可这这样样理理解解:引引用用型型形形参参是是调调用用语语句句处处所所对对应应实实参参变变量量的的别别名名,而而且且系系统统又又将将该该形形参参与与实实参参进进行行了了绑绑定。定。引引用用参参数数的的某某些些内内容容与与用用法法已已在在“5.2.5“5.2.5 值值调调用与引用调用用与引用调用”一节中介绍过,请参阅。一节
46、中介绍过,请参阅。47第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配引用型参数的优点是:引用型参数的优点是:(1 1)它可以把函数外的变量以别名的形式引入到函数)它可以把函数外的变量以别名的形式引入到函数体内参加运算,非常方便,这种方式比用指针解决这体内参加运算,非常方便,这种方式比用指针解决这个问题更合理。个问题更合理。(2 2)它不必在调用时创建与实参变量或对象对应的值)它不必在调用时创建与实参变量或对象对应的值参数变量,当实参变量或对象占用内存较多时,这可参数变量,当实参变量或对象占用内存较多时,这可以节省内存。以节省内存。(3 3)用指针也可以实现类似于引用调用的效果,
47、但由)用指针也可以实现类似于引用调用的效果,但由于指针可以改变内容,任意赋值,因此它不如引用型于指针可以改变内容,任意赋值,因此它不如引用型参数安全。参数安全。48第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配4.4.引用型的函数返回值引用型的函数返回值 非非引引用用型型的的函函数数通通常常仅仅返返回回一一个个值值,而而若若把把函函数数的的返返回回类类型型说说明明为为引引用用型型时时,则则这这个个函函数数除除返返回回一一个个值值外外,而而且且还还返返回回了了它它的的“别别名名”-”-该该函函数数调调用用的的结结果果还还可可以以被被赋赋值值(调调用用结结果果可可以以作左值作左值!
48、)。)。下面给出一个示意性的例子下面给出一个示意性的例子:int&maxr(int&m,int&n)int&maxr(int&m,int&n)/返回值类型为引用类型返回值类型为引用类型 if(mn)if(mn)return m;return m;return n;return n;/由于函数类型为引用,返回的必须是变量(可作左值)由于函数类型为引用,返回的必须是变量(可作左值)这里使用引用型参这里使用引用型参数很重要,否则虽数很重要,否则虽语法上没错,但调语法上没错,但调用结果作为左值时,用结果作为左值时,所作的改变不会反所作的改变不会反映出来。映出来。49第六章第六章 指针,引用与动态内存分
49、配指针,引用与动态内存分配 int a=2,b=4,c;int a=2,b=4,c;c=maxr(a,b);c=maxr(a,b);/OK!/OK!一般性调用,使一般性调用,使c c值为值为4 4maxr(a,b)=88;maxr(a,b)=88;/OK!/OK!函数调用结果相当于变量函数调用结果相当于变量b b的的“别名别名”,/可以作左值可以作左值!使使b b值变为值变为8888maxr(a,b)+;maxr(a,b)+;/OK!/OK!函数调用结果相当于变量函数调用结果相当于变量b b的的“别名别名”,/可以作左值可以作左值!使使b b值增加值增加1 150第六章第六章 指针,引用与动态内存分配指针,引用与动态内存分配引用示例引用示例1-1-引用的建立及简单使用引用的建立及简单使用阅读程序阅读程序P6_6.cpp引用示例引用示例2-2-引用参数及返回引用的函数引用参数及返回引用的函数阅读程序阅读程序P6_7.cpp51