第06章 指针和引用_第1页
第06章 指针和引用_第2页
第06章 指针和引用_第3页
第06章 指针和引用_第4页
第06章 指针和引用_第5页
已阅读5页,还剩81页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、2022-3-121C+高级语言程序设计高级语言程序设计第第6 6章章 指针和引用指针和引用 北京邮电大学北京邮电大学 信息与通信工程学院信息与通信工程学院北京邮电大学信息与通信工程学院指针(Pointer)是C+和C的一种数据类型。很多其他高级语言也有类似的数据类型。引用(Reference)则是C+所特有的一种数据类型。指针和引用在概念上和使用上都有相似之处,但是也有重要的差别。2022-3-12-2-北京邮电大学信息与通信工程学院第六章第六章 指针和引用指针和引用6.1 6.1 指针的概念指针的概念6.2 6.2 指针的运算指针的运算6.3 6.3 指针访问动态内存指针访问动态内存6.4

2、 6.4 指向结构体的指针指向结构体的指针6.5 6.5 引用概念引用概念6.6 6.6 指针和引用作为函数的参数指针和引用作为函数的参数6.7 6.7 指针和引用作为函数的返回值指针和引用作为函数的返回值6.8 6.8 指针和字符串指针和字符串6.9 6.9 通过指针访问数组通过指针访问数组2022-3-12-3-北京邮电大学信息与通信工程学院6.1 6.1 指针的概念指针的概念2022-3-124北京邮电大学信息与通信工程学院2022-3-12北京邮电大学信息与通信工程学院-5-6.1.1 指针和指针变量指针和指针变量指针是变量的地址。或者说是在内存中,存放指针是变量的地址。或者说是在内存

3、中,存放某种类型变量的地址。某种类型变量的地址。例如,定义了整型变量例如,定义了整型变量a a,a a的地址就是一个指的地址就是一个指针。针。也可以不定义任何变量,只是指定内存某个地也可以不定义任何变量,只是指定内存某个地址开始(如址开始(如0 x004301000 x00430100)的)的4 4个字节存放整型个字节存放整型变量,这样的地址也是指针。变量,这样的地址也是指针。存放指针的变量就是指针变量。存放指针的变量就是指针变量。2022-3-12北京邮电大学信息与通信工程学院-6-6.1.1 指针和指针变量指针和指针变量当声明了一个指针变量后,确定如下事实:当声明了一个指针变量后,确定如下

4、事实:n变量本身在内存中所分配的地址和字节数,指针变变量本身在内存中所分配的地址和字节数,指针变量总是占有量总是占有4 4个字节;个字节;n指针所指向的内存单元内可以存放的数据类型。指针所指向的内存单元内可以存放的数据类型。访问指针变量时,只能看到地址。只有通过这访问指针变量时,只能看到地址。只有通过这个地址,才能访问地址单元中的内容。这样的个地址,才能访问地址单元中的内容。这样的访问称为对于内存单元的访问称为对于内存单元的间接访问间接访问。2022-3-12北京邮电大学信息与通信工程学院24-2624-26-7-6.1.2 指针变量的声明和初始化指针变量的声明和初始化 指针变量声明的格式是:

5、指针变量声明的格式是: * *变量名变量名1, 1, * *变量名变量名2 2; ;例如:例如: int *va1, *va2; char *ch1, *ch2;指针变量在声明后,变量的值(地址)是随机指针变量在声明后,变量的值(地址)是随机的。的。这样的指针变量是不能安全的使用的这样的指针变量是不能安全的使用的。因。因为其中的随机地址完全可能不是有效的数据地为其中的随机地址完全可能不是有效的数据地址。址。 2022-3-12北京邮电大学信息与通信工程学院-8-6.1.2 指针变量的声明和初始化指针变量的声明和初始化 在声明指针变量时的在声明指针变量时的“* *”,有两个含义:,有两个含义:n

6、声明变量声明变量va1va1、va2va2、ch1ch1、ch2ch2都是指针变量;都是指针变量;n说明变量说明变量va1va1和和va2va2的类型是(的类型是(int int * *)型,即)型,即指向指向整型变量的指针整型变量的指针。va1va1和和va2va2所指定的地址单元中,所指定的地址单元中,只能存放整型数据。类似地,只能存放整型数据。类似地,ch1ch1和和ch2ch2的类型是的类型是(char char * *)型,它们所指定的地址单元中,只能存)型,它们所指定的地址单元中,只能存放字符。放字符。指针变量都是有类型的指针变量都是有类型的. .指针变量的类型就是指针变量的类型就

7、是它所指定的地址单元中存放的数据的类型它所指定的地址单元中存放的数据的类型。 2022-3-12北京邮电大学信息与通信工程学院-9-6.1.2 指针变量的声明和初始化指针变量的声明和初始化 声明指针变量时进行初始化,其格式是:声明指针变量时进行初始化,其格式是: * *指针变量名指针变量名=&=&变量名变量名; ;n其中的变量名应该是已经声明或定义的同类型变量其中的变量名应该是已经声明或定义的同类型变量名。例如:名。例如:nchar ch1=char ch1=Y Y, ch2=, ch2=A A; ;nchar char * *pch1=&ch1, pch1=&ch1, * *pch2=&ch

8、2;pch2=&ch2;2022-3-12北京邮电大学信息与通信工程学院-10-6.1.2 指针变量的声明和初始化指针变量的声明和初始化 也可以在声明指针变量后,对它进行赋值。也可以在声明指针变量后,对它进行赋值。 例如:例如:nint i1=int i1=Y Y, i2=, i2=A A; ;nint int * *pi1, pi1, * *pi2;pi2;npi1=&i1;pi1=&i1;npi2=&i2;pi2=&i2;没有初始化或赋值的指针变量是不可以使用的。没有初始化或赋值的指针变量是不可以使用的。编译时会给出警告,而运行时会出现错误。编译时会给出警告,而运行时会出现错误。 6.2

9、6.2 指针的运算指针的运算 2022-3-12-11-北京邮电大学信息与通信工程学院6.2 指针的运算指针的运算 表表6.1 6.1 指针的运算指针的运算2022-3-12-12-北京邮电大学信息与通信工程学院2022-3-12北京邮电大学信息与通信工程学院-13-6.2.1 指针的赋值运算指针的赋值运算 指针的赋值运算一定是地址的赋值,可以是:指针的赋值运算一定是地址的赋值,可以是:n同类型变量的地址赋值;同类型变量的地址赋值;n同类型的已经初始化的指针变量赋值。同类型的已经初始化的指针变量赋值。此外,也可以用此外,也可以用0 0或者或者NULLNULL对指针变量赋值。使得变量对指针变量赋

10、值。使得变量包含的是包含的是“空指针空指针”,即不指向任何的内存物理地址。,即不指向任何的内存物理地址。必须注意:不同类型的指针是不可以互相赋值的。在必须注意:不同类型的指针是不可以互相赋值的。在指针赋值时,不存在类型自动转换的机制。指针赋值时,不存在类型自动转换的机制。2022-3-12北京邮电大学信息与通信工程学院-14- 例例6.1 6.1 观察以下指针赋值运算的结果。如果将注释去观察以下指针赋值运算的结果。如果将注释去掉,结果将如何?掉,结果将如何?#include using namespace std;void main()int va1=100,*pva1; float vf1=

11、A,*pvf1,*pvf2; int *pva2=NULL; coutvalue of pva1 is pva2endl; pva1=&va1; pvf1=pvf2=&vf1; coutpva1 &va1endl; coutpvf1 pvf2endl; /pvf1=pva1;value of pva1 is 0 x000000000 x0012FF7C 0 x0012FF7C0 x0012FF74 0 x0012FF74 注释去掉会出现编译错误注释去掉会出现编译错误2022-3-12北京邮电大学信息与通信工程学院-15-6.2.2 间接引用运算间接引用运算 间接引用运算符间接引用运算符“* *

12、”是一种一元算符,它和是一种一元算符,它和指针变量连用,对指针所指向的内存地址单元指针变量连用,对指针所指向的内存地址单元进行间接访问。使用的格式是:进行间接访问。使用的格式是: * *指针变量指针变量如果指针变量如果指针变量iptriptr指向整型变量指向整型变量vava,* *iptriptr就就是变量是变量vava的内容的内容 2022-3-12北京邮电大学信息与通信工程学院-16- 例例6.2 6.2 对变量的直接访问和间接访问:写出以下程序对变量的直接访问和间接访问:写出以下程序运行结果。运行结果。#include #include using namespace std; usin

13、g namespace std; void main()void main()char ch1=a,char ch1=a,* *ch;ch; int k1=100; int k1=100; ch=&ch1; ch=&ch1; /指针指针chch指向变量指向变量ch1ch1 cout cout* *ch=ch=* *chendl;chendl;/间接访问间接访问 * *ch=B; ch=B; coutch1=ch1endl; coutch1=ch1endl;/直接访问直接访问 ch1=k1;ch1=k1; cout cout* *ch=ch=* *chendl; chendl; /间接访问间接访

14、问 运行结果运行结果:*ch=ach1=B*ch=d2022-3-12北京邮电大学信息与通信工程学院-17- 例例6.3 6.3 定义指向指针的指针变量。观察对这种指针变量定义指向指针的指针变量。观察对这种指针变量间接访问的结果。间接访问的结果。#include #include using namespace std;using namespace std;void main()void main() int va=100, int va=100,* *pva,pva,* * *ppva; /ppvappva; /ppva是指向指针的指针是指向指针的指针 int k1=100;int k1=

15、100; pva=&va; pva=&va; cout cout* *pva=pva=* *pvaendl;pvaendl; / /间接访问结果是整型数间接访问结果是整型数 ppva=&pva; ppva=&pva; cout cout* *ppva=ppva=* *ppvaendl; /ppvaendl; /间接访问结果是地址间接访问结果是地址 coutpva=pvaendl;coutpva=pvaendl; / /就是指针就是指针pvapva的内容的内容 运行结果运行结果:*pva=100*ppva=0 x0012FF7C pva=0 x0012FF7C 2022-3-12北京邮电大学信息

16、与通信工程学院-18-6.2.2 间接引用运算间接引用运算2022-3-12北京邮电大学信息与通信工程学院-19-6.2.3 指针的算术运算指针的算术运算 指针可以进行的算术运算只有加法和减法。指针可以进行的算术运算只有加法和减法。指针可以和一个整数指针可以和一个整数n n做加法或者减法运算。做加法或者减法运算。指针指针p p和整数和整数n n相加相加( (相相减减) )的含义是指向当前的含义是指向当前指向位置指向位置p p的前方或后的前方或后方第方第n n个数据的地址。个数据的地址。2022-3-12北京邮电大学信息与通信工程学院-20- 例例6.6.3 3 通过指针的间接访问,输出下标为偶

17、数的数组元通过指针的间接访问,输出下标为偶数的数组元素的值。素的值。# #include include using namespace std;using namespace std;void main() void main() int k110=11,24,37,44,58,66,79,86,93,108, int k110=11,24,37,44,58,66,79,86,93,108,* *k; k; k=&k10; k=&k10; for(int i=0;i10;i=i+2) for(int i=0;i10;i=i+2) coutk1i=coutk1i=* *(k+i) ;(k+i)

18、 ; coutendl; coutendl; 运行结果运行结果:K10=11 k12=37. 数组第一个元素(下标为数组第一个元素(下标为0)的地址赋值给指针)的地址赋值给指针k 每次循环,指针加每次循环,指针加2 22022-3-12北京邮电大学信息与通信工程学院-21-6.2.3 指针的算术运算指针的算术运算指针和指针的直接加法是没有意义的,指针和指针的直接加法是没有意义的,也是不允许的。也是不允许的。 指针和指针的减法是可以进行的,其意指针和指针的减法是可以进行的,其意义是求出两个指针之间可以存放几个指义是求出两个指针之间可以存放几个指定类型的数据。定类型的数据。 不允许用一个整数减一个

19、指针。不允许用一个整数减一个指针。 2022-3-12北京邮电大学信息与通信工程学院-22-6.2.4指针的关系运算和逻辑运算指针的关系运算和逻辑运算 相同类型的指针可以进行各种关系运算。比较相同类型的指针可以进行各种关系运算。比较两个指针相等还是不相等。两个指针相等还是不相等。还可以进行指针还可以进行指针“大于大于”、“小于小于”的比较,的比较,判定指针在内存中的相对位置。判定指针在内存中的相对位置。 指针和一般的整数比较是没有意义的,也是不指针和一般的整数比较是没有意义的,也是不允许的。惟一可以和指针比较的整数是允许的。惟一可以和指针比较的整数是0 0。通。通过指针和过指针和0 0的比较来

20、判定指针本身是不是空指的比较来判定指针本身是不是空指针。针。 2022-3-12北京邮电大学信息与通信工程学院-23-6.2.5 void类型指针类型指针 voidvoid类型的指针就是类型的指针就是“无类型无类型”指针。声明的指针。声明的方式如下:方式如下: void void * * ;voidvoid类型的指针变量中存放的也是内存地址,类型的指针变量中存放的也是内存地址,但是不指定这个地址单元内的数据类型。但是不指定这个地址单元内的数据类型。 2022-3-12北京邮电大学信息与通信工程学院-24-6.2.5 void类型指针类型指针 voidvoid类型的指针的使用:类型的指针的使用:

21、 n任何其他类型的指针都可以赋值给任何其他类型的指针都可以赋值给voidvoid指针。必须指针。必须注意,这样赋值后的注意,这样赋值后的voidvoid指针的类型仍然是指针的类型仍然是voidvoid。 nvoidvoid类型指针不可以直接赋值给任何其他类型的指类型指针不可以直接赋值给任何其他类型的指针。针。 n无论何时,无论何时,voidvoid指针都不可以通过间接引用来访问指针都不可以通过间接引用来访问内存中的数据。内存中的数据。 n要通过要通过voidvoid类型指针访问内存的数据,必须进行指类型指针访问内存的数据,必须进行指针类型的强制转换,才可以通过指针间接引用访问针类型的强制转换,

22、才可以通过指针间接引用访问内存数据。内存数据。 2022-3-12北京邮电大学信息与通信工程学院-25-void类型指针类型指针 voidvoid类型指针还有一个具体的应用:显示字符类型指针还有一个具体的应用:显示字符指针的内容。除了字符指针外,其他指针都可指针的内容。除了字符指针外,其他指针都可以直接用以直接用coutcout语句来输出地址值。但是,用语句来输出地址值。但是,用coutcout输出字符指针时,则是输出它所指向的字输出字符指针时,则是输出它所指向的字符串。可以将字符指针强制转换为符串。可以将字符指针强制转换为voidvoid指针,指针,再用再用coutcout语句输出,就可以看

23、到地址值。如:语句输出,就可以看到地址值。如:char char * *pch=Hello C+;pch=Hello C+;coutpchendl;coutpchendl;cout(voidcout(void* *)pchendl; )pchendl; 2022-3-12北京邮电大学信息与通信工程学院-26- 例例6.6.4 4 使用使用memcpymemcpy通用复制函数复制数组。通用复制函数复制数组。 # #include include using namespace std; using namespace std; #include #include void main()void

24、main() char dest10 char dest10,src10=012345678“; src10=012345678“; char char* * pc=(char pc=(char* *)memcpy(dest,src,10);)memcpy(dest,src,10); cout pc endl;cout pc endl; int s13=1,2,3 int s13=1,2,3,d13; d13; int int * *pi=(intpi=(int* *)memcpy(d1,s1,12);)memcpy(d1,s1,12); coutcout* *pi pi * *(pi+1)

25、(pi+1) * *(pi+2)endl;(pi+2)endl; / / void void * *memcpy(void memcpy(void * *dest, const void dest, const void * *src, size_t n);src, size_t n);运行结果运行结果:0123456780123456781 2 3 2022-3-12北京邮电大学信息与通信工程学院-27-6.2.6 指针类型转换指针类型转换实际应用的指针变量都是有类型的,指针类型就是实际应用的指针变量都是有类型的,指针类型就是指针所指的地址空间所存放的数据的类型。指针所指的地址空间所存放的数

26、据的类型。除了除了voidvoid指针,不同类型的指针是不可以相互赋值指针,不同类型的指针是不可以相互赋值的。在例的。在例6-16-1中的语句中的语句pvf1=pva1(pvf1=pva1(整型指针赋值给整型指针赋值给floatfloat指针指针) )就是有语法错误的语句。就是有语法错误的语句。一般地,指针也不能进行强制类型转换。(?)一般地,指针也不能进行强制类型转换。(?)2022-3-12北京邮电大学信息与通信工程学院-28-指针类型转换指针类型转换若若pchpch是字符指针,是字符指针,p p是是doubledouble类型指针,以下的语句:类型指针,以下的语句: pch=static

27、_castcharpch=static_cast(p);(p); 在编译时有语法错误:在编译时有语法错误:“不能将不能将doubledouble* *转换为转换为charchar* *”,也就是说指针的强制类型转换也是不允许,也就是说指针的强制类型转换也是不允许的。的。如果使用如果使用C C风格的类型转换:风格的类型转换:pch=(charpch=(char* *)p;)p;在编译时在编译时没有语法错误,仅在执行时有问题。没有语法错误,仅在执行时有问题。要使用要使用static_caststatic_cast来进行强制类型转换。来进行强制类型转换。voidvoid指针和其它类型指针之间可以相互

28、转换。指针和其它类型指针之间可以相互转换。2022-3-12北京邮电大学信息与通信工程学院-29-/例6-5利用格式控制符hex可以显示整数的机器数的程序void main()void main() float f=1.0; float f=1.0; floatfloat* * fPtr=&f; / fPtr=&f; /浮点指针浮点指针 voidvoid* * fv=&f; fv=&f;intint* * iPtr=static_castint iPtr=static_cast(fv); (fv); / /浮点变量地址赋给整型指针浮点变量地址赋给整型指针 cout f endlcout f e

29、ndl iPtr: iPtr iPtr: iPtr * *iPtr iPtr hexhex* *iPtrendliPtrendl fPtr: fPtr fPtr: fPtr * *fPtr endl ;fPtr endl ; 6.3 6.3 指针访问动态内存指针访问动态内存2022-3-12-30-北京邮电大学信息与通信工程学院指针访问动态内存指针访问动态内存 动态内存是在程序执行时才可以申请、使用和释放的内存。也就是存放动态数据的内存区域。存放动态数据的区域称为“堆”,动态内存也称为堆内存堆内存。 动态内存不能通过变量名来使用,而只能通过指针来使用。 2022-3-12-31-北京邮电大学信

30、息与通信工程学院2022-3-12北京邮电大学信息与通信工程学院-32-6.3.1 动态内存的申请和释放动态内存的申请和释放C+C+中通过运算符中通过运算符newnew申请动态内存,运算符申请动态内存,运算符deletedelete释放动态内存。释放动态内存。 动态内存申请运算符动态内存申请运算符newnew的使用格式:的使用格式: new new ( (初值初值) ) n运算的结果:如果申请成功,返回指定类型内存的运算的结果:如果申请成功,返回指定类型内存的地址;如果申请失败,返回地址;如果申请失败,返回NULLNULL指针。指针。动态内存使用完毕后,要用动态内存使用完毕后,要用delete

31、delete运算来释放。运算来释放。deletedelete运算符使用格式:运算符使用格式: delete delete ; ; 2022-3-12北京邮电大学信息与通信工程学院-33-6.3.2 动态数组空间的申请和释放动态数组空间的申请和释放对于数组情况,需要在对于数组情况,需要在newnew表达式中加上申请表达式中加上申请数组的大小:数组的大小: new new 常量表达式常量表达式 ; ; n注意:在动态申请数组空间时,不可以对数组进行注意:在动态申请数组空间时,不可以对数组进行初始化。初始化。 n也可以申请二维数组的空间:也可以申请二维数组的空间:int (int (* *pi_ma

32、rray)4;pi_marray)4;pi_marray = new int34; pi_marray = new int34; 释放动态数组空间都用相同的表达式:释放动态数组空间都用相同的表达式: delete delete ; 2022-3-12北京邮电大学信息与通信工程学院-34-6.3.3 内存泄漏和指针悬挂内存泄漏和指针悬挂 内存泄漏是指动态申请的内存空间,没有正常内存泄漏是指动态申请的内存空间,没有正常释放,但是也不能继续使用的情况。如:释放,但是也不能继续使用的情况。如: char char * *ch1;ch1;ch1 = new char(A);ch1 = new char(

33、A);char char * *ch2 = new char;ch2 = new char;ch1=ch2; ch1=ch2; 原来为原来为ch1ch1所申请的存放字符所申请的存放字符A A的空间不能被释放,的空间不能被释放,产生了内存泄漏。产生了内存泄漏。 2022-3-12北京邮电大学信息与通信工程学院-35-6.3.3 内存泄漏和指针悬挂内存泄漏和指针悬挂让指针指向一个已经释放的空间,即所谓的指让指针指向一个已经释放的空间,即所谓的指针悬挂针悬挂( (Dangling)Dangling)。如:如: char char * *ch1, ch1, * *ch2;ch2;ch1 = new c

34、har;ch1 = new char;ch2 = ch1;ch2 = ch1;* *ch2 = B;ch2 = B;delete ch1; delete ch1; 指针指针ch2ch2指向了一个已经释放的地址空间,产生指针悬指向了一个已经释放的地址空间,产生指针悬挂。若要用挂。若要用delete ch2;delete ch2;语句来释放语句来释放ch2ch2所指向的空间,所指向的空间,会出现运行错误。会出现运行错误。 6.4 6.4 指向结构体的指针指向结构体的指针2022-3-12-36-北京邮电大学信息与通信工程学院 指向结构体的指针指向结构体的指针定义变量时,可以定义指向定义变量时,可以

35、定义指向intint型的指针变量,型的指针变量,也可以定义指向结构体类型的指针变量。也可以定义指向结构体类型的指针变量。声明了指向结构体的指针后,可以对指针初始声明了指向结构体的指针后,可以对指针初始化:其一是用已经定义的变量地址来初始化,化:其一是用已经定义的变量地址来初始化,其二是用其二是用newnew申请一个地址来对指针初始化。申请一个地址来对指针初始化。 2022-3-12-37-北京邮电大学信息与通信工程学院2022-3-12北京邮电大学信息与通信工程学院-38-举例:举例:(1)(1)struct student struct student /声明新的数据类型声明新的数据类型 l

36、ong num; long num;/学号学号 char name20; char name20; /姓名姓名 float score;float score;/成绩成绩;student stu=20041118,Li Li,18;student stu=20041118,Li Li,18; / /定义结构变量并初始化定义结构变量并初始化student student * * ps=&stu; ps=&stu; /定义结构体指针并初始化定义结构体指针并初始化(2) (2) student student * * ps=new student; ps=new student; / /定义结构体指

37、针始化定义结构体指针始化2022-3-12北京邮电大学信息与通信工程学院-39-用结构指针访问结构成员时,用箭头操作符代替原来的点操作符对结构体成员进行操作。比如,把学生的成绩输出显示:coutscore;其中,ps-score等价于(*ps).score。2022-3-12北京邮电大学信息与通信工程学院-40-解:员工信息包括姓名、工作证号、薪水,可定义为结构体类型。#include #include using namespace std;struct Employee char name20; unsigned long id; float salary;例例6-6 显示员工信息显示员工

38、信息2022-3-12北京邮电大学信息与通信工程学院-41-void main() Employee pr1, *prPtr; prPtr=&pr1; strcpy(prPtr-name,zhang san); prPtr-id=98001,prPtr-salary=3350.0; coutnameprPtr-name id prPtr-id salary prPtr-salary endl;程序运行结果:zhang san 98001 33506.5 6.5 引用概念引用概念2022-3-12-42-北京邮电大学信息与通信工程学院2022-3-12北京邮电大学信息与通信工程学院-43-引用概

39、念引用概念引用(引用(Reference)是是C+中新引入的概念,也是中新引入的概念,也是C语言中不存在的数据类型。语言中不存在的数据类型。 引用是变量或者其他编程实体(如对象)的别名引用是变量或者其他编程实体(如对象)的别名。如图如图6.4(a)所示,变量所示,变量A在内存中有自己的地址,在内存中有自己的地址,而而A的引用的引用B实际上就是变量实际上就是变量A,只是只是A的另外一个的另外一个名字。名字。 2022-3-12北京邮电大学信息与通信工程学院-44-6.5.1 引用的声明引用的声明引用是通过运算符&来定义的,定义的格式如下: &引用名 = 变量名;其中的变量名必须是已经定义的,并且

40、和引用的类型必须相同。例如: int someInt;int &refInt = someInt;必须注意:引用必须在声明的时候就完成初始化,不可以先声明引用,然后再用另一个语句对它赋值。 2022-3-12北京邮电大学信息与通信工程学院-45-引用有以下的特点: n引用不能独立存在,它只是其他变量的别名; n引用必须在声明的同时就初始化; n引用一旦定义,引用关系就不可以更改,即B若是A的引用,就不可能是其他变量的引用; n引用的类型就是相关变量的类型,引用的使用和变量的使用相同。 2022-3-12北京邮电大学信息与通信工程学院-46- 例6-7 使用引用 void main() int

41、intA=10; int& refA=intA; coutrefA=refAendl; refA=5; cout“intA=intAendl; cout“intA的地址&intAendl; cout“refA的地址&refAendl;6.5.2 引用的使用引用的使用 运行结果运行结果:refA=10intA=5intA的地址0 x0012FF7CrefA的地址0 x0012FF7C6.66.6指针和引用作为函数的指针和引用作为函数的参数参数2022-3-12-47-北京邮电大学信息与通信工程学院2022-3-12北京邮电大学信息与通信工程学院-48-指针和函数指针和函数在程序设计中,指针有很多

42、应用。其中之一就是用指针作为函数的参数。 2022-3-12北京邮电大学信息与通信工程学院-49-6.6.1 指针作为函数的参数指针作为函数的参数用指针作为函数参数,必须满足以下条件: n函数的形式参数是指针变量; n函数的实参数是内存的地址,具体来说可以是数组名、变量的地址、地址常量;n形参指针类型和实参地址类型必须相同。 2022-3-12北京邮电大学信息与通信工程学院-50-6.6.1 指针作为函数的参数指针作为函数的参数满足以上条件后,这样的函数调用有以下特点: n实参传递给形参的是内存的地址,所以形参指针指向实参变量; n形参指针通过间接引用,直接访问实参变量,包括改变实参变量的值;

43、 n函数调用后,可以保留对实参变量的操作结果,如果有多个实参,就可以有多个实参变量在函数调用中得到修改。 2022-3-12北京邮电大学信息与通信工程学院-51- 例例6.6.8 8 数据交换数据交换 void Swap(int *a, int *b);void main() int x(5), y(10); cout“x=x y=yendl;Swap(&x,&y);cout“x=x“ y=yendl;void Swap(int *a, int *b) int t;t=*a, *a=*b, *b=t; 运行结果运行结果:x=5 y=10 x=10 y=5 变量的地址作为实参数变量的地址作为实参

44、数指针变量作为形式参数指针变量作为形式参数2022-3-12北京邮电大学信息与通信工程学院-52-6.6.1 指针作为函数的参数指针作为函数的参数程序中用变量x和y的地址作实参,传递给指针a和b,如图6.1(a)。通过间接引用*a和*b进行交换,实际上就是x和y进行交换,如图6.1(b)。 2022-3-12北京邮电大学信息与通信工程学院-53-6.6.2 引用作为函数参数引用作为函数参数引用使用最多的场合是作为函数的形参。 引用作为函数的形参具有以下的特点: n实参是相同类型的变量; n参数传递属于地址传递; n在函数中并不产生实参的副本,形参引用和实参变量实际上是同一个实体; n函数对引用

45、的操作,也是对实参变量的操作,函数调用可以改变实参的值。 2022-3-12北京邮电大学信息与通信工程学院-54- 例例6.6.9 9 引用作为形参,通过函数调用,交换两个实参的值。 void swap_1(int &x, int &y) /引用作为形式参数 int j; j=x, x=y, y=j;void main() int a=12345, b=54321; cout “ 调用前:a= a b=bendl; swap_1(a, b); /变量作为实参数 cout “ 调用后:a= a b=bendl; 调用前:调用前:a= 12345 b=54321a= 12345 b=54321 调

46、用后:调用后:a= 54321 b=12345a= 54321 b=123452022-3-12北京邮电大学信息与通信工程学院-55-6.6.2 引用作为函数参数引用作为函数参数引用作为形参需要注意:引用作为形参需要注意: n如果实参要保护,可使用“常引用”作为形式参数; n引用作形参和变量作形参虽有区别,但要注意以下用法。 例:swap(int a, int b); swap(int &a, int&b); 虽然两个函数的原型不同,但在以下情况会出现“二义性”错误。 swap(x, y); / x,y是int变量2022-3-12北京邮电大学信息与通信工程学院-56-6.6.3 常指针和常引

47、用常指针和常引用常指针是指向常量的指针(Pointer to Constant data),它规定指针所指向的内容不可以通过指针的间接引用(间接访问)来改变。 常指针说明的格式是: const *; 例如: const int *ptint; 指针ptint的类型是(const int *),也就是指向一个恒定的整型数。 2022-3-12北京邮电大学信息与通信工程学院-57- 例例6.10 6.10 使用使用常指针常指针#include using namespace std;void main() int ia=10, ib=20; const int *ptint; ptint=&ia;

48、/用ia地址初始化 cout*ptintendl; ptint=&ib;/改变为ib的地址 ib=ib+100;/ib本身仍然可以改变 cout*ptintendl; /*ptint=100; /语句错误 运行结果运行结果:10 120 常指针声明常指针声明2022-3-12北京邮电大学信息与通信工程学院-58-6.6.4 指针的指针作为函数的参数指针的指针作为函数的参数如果一定要改变实参指针的值,可以用指针变量的地址作实参,形式参数就应该是指针的指针。 2022-3-12北京邮电大学信息与通信工程学院-59- 例例6.6.1212 指针变量指向数组。指针变量指向数组。void Move(in

49、t *a);void main() int x5=10,20,30,40,50, *px=x;cout调用前的*px=*pxendl; Move(px);cout调用后的px;if(px=x)cout没有变化,*px还是*pxendl;else cout也向前移动,*px变为*pxendl;void Move(int *a) a=a+1; cout函数中完成了指针移动:*a=*aendl; 运行结果:调用前的*px=10 函数中完成了指针移动:*a=20 调用后的px没有变化*px还是10 2022-3-12北京邮电大学信息与通信工程学院-60- 例例6.6.1313:修改上例,使得实参指针返

50、回后,指向新地址。 void Move(int *a);void main() int x5=10,20,30,40,50, *px=x;cout*px=*pxendl;Move(&px); coutpx;if(px=x)cout没有变化,*px还是*pxendl;else cout向前移动,*px变为*pxendl;void Move(int *a) *a=*a+1; cout*a=*aendl; 运行结果:*px=10 *a=20 px向前移动,*px变为20 指针的地址作为实参数指针的地址作为实参数指针的指针作为形式参数指针的指针作为形式参数6.76.7指针和引用作为函数的指针和引用作为

51、函数的返回值返回值2022-3-12-61-北京邮电大学信息与通信工程学院?2022-3-12北京邮电大学信息与通信工程学院-62-6.7.1 指针函数指针函数 如果一个函数的返回值是指针,则这样的函数如果一个函数的返回值是指针,则这样的函数称为指针函数。如:称为指针函数。如: int int * *func01(int k);func01(int k); n函数函数func01func01返回一个指向整型数据的指针。返回一个指向整型数据的指针。 n返回指针,实际就是返回一个内存的地址。返回指针,实际就是返回一个内存的地址。n要注意:要注意:不能返回函数中局部变量的地址。不能返回函数中局部变量

52、的地址。这样的这样的地址处于内存的堆栈区,是所有函数公用的区域。地址处于内存的堆栈区,是所有函数公用的区域。其中的数据是不稳定的,可能因为其他函数的执行其中的数据是不稳定的,可能因为其他函数的执行而发生改变。而发生改变。 2022-3-12北京邮电大学信息与通信工程学院-63- 例例6-15 6-15 一个指针函数完成一个数组的倒序。源数组由函一个指针函数完成一个数组的倒序。源数组由函数参数传递,倒序后的数组地址由指针函数返回。数参数传递,倒序后的数组地址由指针函数返回。 #include #include using namespace std;using namespace std;int

53、 int * * reverse(int const reverse(int const * * list, const int size) list, const int size)/ /指针函数指针函数 int result6; int result6;/ /函数中定义的局部数组函数中定义的局部数组 for (int i = 0, j = size - 1; i size; i+, j-)for (int i = 0, j = size - 1; i size; i+, j-) resultj = listi; resultj = listi; return result; return

54、result;/ /返回局部数组的地址返回局部数组的地址 2022-3-12北京邮电大学信息与通信工程学院-64- void printArray(int const void printArray(int const * *list, const int size)list, const int size) for (int i = 0; i size; i+) for (int i = 0; i size; i+) cout listi ; cout listi ; void main()void main() int list = 1, 2, 3, 4, 5, 6; int list =

55、 1, 2, 3, 4, 5, 6; int int * *pList = reverse(list, 6); /pList = reverse(list, 6); /获得倒序后数组的地址获得倒序后数组的地址 printArray(pList, 6);printArray(pList, 6);/ /显示倒序后的数组显示倒序后的数组 程序运行结果:程序运行结果:-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 5 858993460 5 结果完全不对

56、。原因就在于指针函数返回的是函数局部数组结果完全不对。原因就在于指针函数返回的是函数局部数组的地址。的地址。2022-3-12北京邮电大学信息与通信工程学院-65- 例例6-16 6-16 对例对例6-156-15的修改。只要修改指针函数的修改。只要修改指针函数reversereverse。可。可以在函数这申请一个动态数组的地址,最后返回这个地址以在函数这申请一个动态数组的地址,最后返回这个地址就可以。注意不要忘了用就可以。注意不要忘了用deletedelete来释放这个地址。来释放这个地址。#include #include using namespace std;using namespa

57、ce std;int int * * reverse(int const reverse(int const * * list, const int size) list, const int size)/ /指针函数指针函数 int int * *result = new intsize;result = new intsize;/ /函数中定义的动态数组函数中定义的动态数组 for (int i = 0, j = size - 1; i size; i+, j-)for (int i = 0, j = size - 1; i size; i+, j-) resultj = listi; r

58、esultj = listi; return result; return result; / /返回动态数组的地址返回动态数组的地址 2022-3-12北京邮电大学信息与通信工程学院-66- void printArray(int const void printArray(int const * *list, const int size)list, const int size) for (int i = 0; i size; i+) for (int i = 0; i size; i+) cout listi ; cout listi ; void main()void main()

59、int list = 1, 2, 3, 4, 5, 6; int list = 1, 2, 3, 4, 5, 6; int int * *pList = reverse(list, 6);pList = reverse(list, 6);/ /获得倒序后数组的地址获得倒序后数组的地址 printArray(pList, 6printArray(pList, 6); ;/ /显示倒序后的数组显示倒序后的数组 delete pList;delete pList; 程序运行结果:程序运行结果:6 5 4 3 2 16 5 4 3 2 12022-3-12北京邮电大学信息与通信工程学院-67-6.7.

60、2 用用引用作为函数的返回值引用作为函数的返回值返回引用有以下需要注意的地方:返回引用有以下需要注意的地方: n返回引用需要在函数的返回值类型中加以说明,形返回引用需要在函数的返回值类型中加以说明,形式为:式为: & &函数名函数名( (形式参数表形式参数表) ) n返回引用的返回语句就是:返回引用的返回语句就是:return return 变量名变量名; ; n返回引用实际是返回地址。在使用上,或者直接使返回引用实际是返回地址。在使用上,或者直接使用这个地址;或者使用这个地址单元的数据。用这个地址;或者使用这个地址单元的数据。 n返回的引用可以作为左值继续操作返回的引用可以作为左值继续操作,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论