C++大学基础教程第六章课件

上传人:202****8-1 文档编号:242626409 上传时间:2024-08-29 格式:PPT 页数:81 大小:527.57KB
返回 下载 相关 举报
C++大学基础教程第六章课件_第1页
第1页 / 共81页
C++大学基础教程第六章课件_第2页
第2页 / 共81页
C++大学基础教程第六章课件_第3页
第3页 / 共81页
点击查看更多>>
资源描述
,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,北京邮电大学电信工程学院计算机技术中心,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,北京邮电大学电信工程学院计算机技术中心,*,2024/8/29,1,C+,大学基础教程,第,6,章 指针和引用,2023/9/51C+大学基础教程第6章 指针和引用,2024/8/29,2,指针(,Pointer,)是,C+,和,C,的一种数据类型。很多其他高级语言也有类似的数据类型。,引用(,Reference,)则是,C+,所特有的一种数据类型。,2023/9/52指针(Pointer)是C+和C的一种数,2024/8/29,3,第六章 指针和引用,6.1,指针的概念,6.2,指针的运算,6.3,指针和函数,6.4,指针和字符串,6.5,通过指针访问数组,6.6,指针访问动态内存,6.7,引用概念,2023/9/53第六章 指针和引用6.1 指针的概念,2024/8/29,4,6.1,指针的概念,2023/9/546.1 指针的概念,2024/8/29,5,6.1.1,指针和指针变量,指针是变量的,地址,例如,定义整型变量,a,,,a,的地址就是,一个指针。,直接指定内存某个地址开始(如,0x00430100,),存放指针的变量就是指针变量。,2023/9/556.1.1 指针和指针变量指针是变量的地址,2024/8/29,6,6.1.1,指针和指针变量,当声明了一个指针变量后,确定了三件事:,1.,变量本身在内存中所分配的地址和字节数,(,4,个,),2.,系统允许的地址范围,及地址单元内可以存放的内容,3.,指针变量可以进行的运算,访问指针变量时,只能看到地址,通过这个地址访问地址单元中的内容,这样的访问称为对于内存单元的,间接访问,。,2023/9/566.1.1 指针和指针变量当声明了一个指针,2024/8/29,7,6.1.2,指针变量的声明和初始化,指针变量声明的格式是:,类型名,*,变量名,1, *,变量名,2,;,例如:,int *va1, *va2;,char *ch1, *ch2;,指针变量在声明后,变量的值(地址)是随机的。,这样的指针变量是不能安全的使用的,2023/9/576.1.2 指针变量的声明和初始化 指针变,2024/8/29,8,6.1.2,指针变量的声明和初始化,在声明指针变量时的,“,*,”,,有两个含义:,声明变量,va1,、,ch1,、,ch2,都是指针变量;,说明变量,va1,的类型是(,int *,)型,即,指向整型变量的指针,。,ch1,和,ch2,的类型是(,char *,)型,指针变量都是有类型的,-,所指定的地址单元中存放的数据的类型,2023/9/586.1.2 指针变量的声明和初始化 在声明,2024/8/29,9,6.1.2,指针变量的声明和初始化,指针变量必须,初始化后,才能,安全使用,声明指针变量时进行初始化的格式:,类型名,*,指针变量名,=&,变量名,;,char ch1=,Y, ch2=,A,;,char *pch1=,2023/9/596.1.2 指针变量的声明和初始化 指针变,2024/8/29,10,6.1.2,指针变量的声明和初始化,赋值方式进行初始化:,int i1=,Y, i2=,A,; int *pi1, *pi2;,pi1=,pi2=,没有初始化的指针变量不可以使用,(,编译系统会给出警告,而运行时会出现错误,),2023/9/5106.1.2 指针变量的声明和初始化 赋值,2024/8/29,11,6.2,指针的运算,2023/9/5116.2 指针的运算,2024/8/29,12,6.2,指针的运算,表,6.1,指针的运算,2023/9/5126.2 指针的运算,2024/8/29,13,6.2.1,指针的赋值运算,指针的赋值,:,地址的赋值,同类型变量的地址,同类型的已经初始化的指针变量;,其他同类型的指针,用,0,或者,NULL,赋值,“,空指针,”,,即不指向任何的内存物理地址,不同类型的指针不可以互相赋值,在指针赋值时,不存在类型自动转换的机制,2023/9/5136.2.1 指针的赋值运算 指针的赋值:,2024/8/29,14,例,6.1,观察以下指针赋值运算的结果。如果将注释去掉,结果将如何?,#include ,using namespace std;,void main(),int va1=100,*pva1; int *pva2=NULL;,float vf1=A,*pvf1,*pvf2;,coutvalue of pva2 is pva2endl;,pva1=,pvf1=pvf2=,coutpva1 ,coutpvf1 pvf2endl;,/pvf1=pva1;,value of pva2 is 0x00000000,0x0012FF7C 0x0012FF7C,0x0012FF74 0x0012FF74,注释去掉会出现编译错误,2023/9/514 例6.1 观察以下指针赋值运算的结果。,2024/8/29,15,6.2.2,间接引用运算,间接引用运算符,“,*,”,:,一元运算符,和指针变量连用,对指针所指向的内存地址单元进行间接访问,使用的格式:,*指针变量,如果指针变量,iptr,指向整型变量,va,*,iptr,就是变量,va,的内容,2023/9/5156.2.2 间接引用运算 间接引用运算符,2024/8/29,16,例,6.2,对变量的直接访问和间接访问,#include ,using namespace std;,void main(),char ch1=a,*ch;,int k1=100;,ch= /,指针,ch,指向变量,ch1,cout*ch=*chendl;/,间接访问,*,ch=B;,coutch1=ch1endl;/,直接访问,ch1=k1;,cout*ch=*chendl; /,间接访问,运行结果,:,*ch=a,ch1=B,*ch=d,2023/9/516 例6.2 对变量的直接访问和间接访问运,2024/8/29,17,例,6.3,观察对这种指针变量间接访问的结果。,#include ,using namespace std;,void main(), int va=100,*pva,*ppva;,/ppva,是指向指针的指针,int k1=100;,pva=,cout*pva=*pvaendl;,/,间接访问结果是整型数,ppva=,cout*ppva=*ppvaendl;,/,间接访问结果是地址,coutpva=pvaendl;,/,就是指针,pva,的内容,运行结果,:,*pva=100,*ppva=0x0012FF7C,pva=0x0012FF7C,2023/9/517 例6.3 观察对这种指针变量,2024/8/29,18,6.2.2,间接引用运算,2023/9/5186.2.2 间接引用运算,2024/8/29,19,6.2.3 指针的算术运算,可以进行的只有,加法和减法,-,和整数,n,做加法或者减法,指针,p,和整数,n,相加(相减)的含义是指向当前指向位置,p,的前方或后方第,n,个数据的地址。,2023/9/5196.2.3 指针的算术运算 可以进行的只,2024/8/29,20,例6.4 通过指针的间接访问,输出下标为偶数的数组元素的值。,#,include ,using namespace std;,void main(),int k110=11,24,37,44,58,66,79,86,93,108,*k;,k=,for(int i=0;i10;i=i+2),coutk1i=*(k+i) ;,coutendl;,运行结果,:,K10=11 k12=37.,数组第一个元素(下标为,0,)的地址赋值给指针,k,每次循环,指针加,2,2023/9/520 例6.4 通过指针的间接访问,输出下标,2024/8/29,21,6.2.3 指针的算术运算,指针和指针的,直接加法没有意义,指针和指针的,减法可以,进行,-,求出两个指针之间可以存放几个指定类型的数据,不允许用一个整数减一个指针,2023/9/5216.2.3 指针的算术运算指针和指针的直,2024/8/29,22,6.2.4,指针的关系运算和逻辑运算,同类型,的指针,可以,进行关系运算,进行指针,“,大于,”,、,“,小于,”,的比较,是判定指针在内存中的相对位置,指针和一般的整数比较没有意义,也不允许,惟一可以和指针比较的整数是0。判定指针是不是空指针,2023/9/5226.2.4指针的关系运算和逻辑运算 同,2024/8/29,23,6.2.5,void,类型指针,void,类型的指针就是,“,无类型,”,指针:,void *,指针名;,存放的也是内存的地址,但不指定这个地址单元内的数据的类型,2023/9/5236.2.5 void类型指针 void类,2024/8/29,24,6.2.5,void,类型指针使用要点,-,任何指针都可以赋值给,void,指针,赋值后的,void,指针的类型仍然是,void,-void,指针不可以赋值给其他任何类型的指针,-void,指针不可通过间接引用访问内存中数据,-,必须进行指针类型的强制转换,才可以使用指针间接引用访问内存数据,2023/9/5246.2.5 void类型指针使用要点 -,2024/8/29,25,例,6.5,使用,memcpy,通用复制函数复制数组,原型,void *memcpy(void *dest, const void*, size),#,include ,using namespace std;,#include ,void main(),char src10=012345678;,char dest10;,char* pc=(char*)memcpy(dest,src,10);,cout pc endl;,int s13=1,2,3;,int d13;,int *pi=(int*)memcpy(d1,s1,12);,cout*pi *(pi+1) *(pi+2)endl;,运行结果,:,012345678,1 2 3,复制字符数据,10个字节,复制整型数据,12个字节,2023/9/525 例6.5 使用memcpy通用复制函数,2024/8/29,26,6.2.5,void,类型指针,void,类型指针应用:,显示字符指针的内容,其他指针直接用,cout,语句输出地址值,而字符指针输出的是字符串,将字符指针强制转换为,void,指针,cout,语句输出便是地址值,例:,char *pch=Hello C+;,coutpchendl;,cout(void*)pchendl;,2023/9/5266.2.5 void类型指针 void类,2024/8/29,27,指针是地址,int *p;,p=,*p=100; b=*p+2;,2023/9/527指针是地址int *p;*p=100;,2024/8/29,28,6.3,指针和函数,2023/9/5286.3 指针和函数,2024/8/29,29,6.3 指针和函数,在程序设计中,指针有很多应用,其中之一就是,作为函数的参数,,形成了,C+,函数调用中的另一种调用方式:,地址调用,2023/9/5296.3 指针和函数在程序设计中,指针有很,2024/8/29,30,6.3.1 指针作为函数的参数,实现地址调用,必须满足以下条件:,函数的,形式参数是指针变量,;,函数的,实参数是内存的地址,(可以是,数组名,、,变量的地址,、用变量地址初始化的,指针,),形参指针类型和实参地址,类型必须相同,2023/9/5306.3.1 指针作为函数的参数实现地址调,2024/8/29,31,6.3.1 指针作为函数的参数,实参传递给形参的是内存的地址,所以形参指针指向实参变量,形参指针,通过间接引用,,,直接访问实参变量,(包括改变实参变量的值),函数调用后,改变了实参,如果有多个实参,就可以有多个实参变量在函数调用中被修改,2023/9/5316.3.1 指针作为函数的参数,2024/8/29,32,例,6.6,编写数据交换的函数。,#include,void Swap(int *a, int *b);,void main(),int x(5), y(10);,cout,主函数变量的值:,x=x y=yendl;,Swap(,cout,返回后变量的值:,x=x y=yendl;,void Swap(int *a, int *b),int t;,t=*a;,*a=*b;,*b=t;,cout,函数中完成了交换:,*,a=*a *b=*bendl;,运行结果,:,主函数变量的值:,x=5 y=10,函数中完成了交换:,*,a=10 *b=5,返回后变量的值:,x=10 y=5,变量的地址作为实参数,指针变量作为形式参数,2023/9/532 例6.6 编写数据交换的函数。运行结果,2024/8/29,33,6.3.1 指针作为函数的参数,变量,x,和,y,的地址作实参传递给指针,a,和,b,如图,(,a),通过间接引用,*,a,和,*,b,进行交换,实际上就是,x,和,y,进行交换,如图,(,b),2023/9/5336.3.1 指针作为函数的参数变量x和y,2024/8/29,34,例,6.7,指针变量指向一个数组,#include,using namespace std;,void Move(int *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; *a=100;,cout,“,函数中完成了指针,移动:,*,a=*aendl;,运行结果,:,调用前的,*,px=10,函数中完成了指针移动:,*,a=20,调用后的,px,没有变化,*,px,还是,10,指针作为实参数,指针变量作为形式参数,2023/9/534 例6.7 指针变量指向一个数组运行结果,2024/8/29,35,6.3.3 传递参数的保护:指针和常量,通过数组名地址调用,,可以,改变实参数组内容,但有时并不需要改变数组的值,例如,在调用一个求数组最大值的函数时,就不希望数组的值发生变化,希望在函数中能够限制对数组元素的修改,使用,常指针,可以达到这个目的,2023/9/5356.3.3 传递参数的保护:指针和常量,2024/8/29,36,6.3.3 传递参数的保护:指针和常量,常指针,是指向常量的指针,(,Pointer to Constant data),规定指针所指向的内容不可以通过指针的间接引用来改变,。,常指针说明的格式是:,const,类型名 *指针名;,例如:,const int *ptint;,指针,ptint,的类型是(,const int *),,即指向一个恒定的整型数,2023/9/5366.3.3 传递参数的保护:指针和常量,2024/8/29,37,例,6.10,常指针示例。观察以下程序的运行。,#include ,using namespace std;,void main(),int ia=10, ib=20;,const int *ptint;,ptint=,/,用,ia,地址初始化,cout*ptintendl;,ptint=,/,改变为,ib,的地址,ib=ib+100;,/ib,本身仍然可以改变,cout*ptintendl;,/ *ptint=100;,/,语句错误:左值是常量,运行结果,:,10,120,常指针声明,注释去掉会出现编译错误,2023/9/537 例6.10 常指针示例。观察以下程序的,2024/8/29,38,6.3.3 传递参数的保护:指针和常量,指针常量,(,Pointer constant,),指针本身是常量,(,地址是常量,),不可以改变,指针常量声明的格式:,类型名,*,const,指针名,=,初值,;,char ch, *const ptch=,数组名是数组的首地址,-,数组名是指针常量,2023/9/5386.3.3 传递参数的保护:指针和常量,2024/8/29,39,例6.11 指针常量示例。指出以下程序的错误。,#include ,using namespace std;,void main(),int a=10, b=100;,int *const pa=,/pa,是指针常量,cout*paendl;,*pa=20;,/,指针常量的间接引用是允许的,coutaendl;,pa=,const int c=50;,int *const pc=,错误语句注释掉后运行结果,:,10,20,语句有错:常量不能当左值,语句有错,地址类型不同,不能用常量地址初始化指针常量,2023/9/539 例6.11 指针常量示例。指出以下程序,2024/8/29,40,例,6.12,用常指针作形参,函数,printString,可以输出数组的内容,不可以对数组修改。,#include ,using namespace std;,void printString( const char * );,void main(), char phrase = C+ is a programming language;,cout The string is:n;,printString( phrase ); cout endl;, / main,函数结束,void printString( const char *Ptarray ), while(*Ptarray),cout *Ptarray+;,不使用常指针也是可以完成打印。但是没有保护了。,数组名作实参数,常指针作形式参数,2023/9/540 例6.12 用常指针作形参,函数pri,2024/8/29,41,6.4,指针和字符串,2023/9/5416.4 指针和字符串,2024/8/29,42,6.4.1 字符串处理的两种方式,字符串常量,:双引号括起,,0,结束 如:,This is a string。,字符串常量有自己固定的首地址,如果将字符串常量的首地址看成是指针,这种指针既是常指针,也是指针常量。,2023/9/5426.4.1 字符串处理的两种方式字符串常,2024/8/29,43,6.4.1 字符串处理的两种方式,处理字符串两种方式:,数组方式,和,指针方式,数组方式,是将字符串存入字符数组:,char string_array, ,=What,s a nice day!;,指针方式,是用字符串常量来初始化一个字符指针:,char,*,string_pt=What,s a nice day!;,2023/9/5436.4.1 字符串处理的两种方式处理字符,2024/8/29,44,6.4.1 字符串处理的两种方式,指针常量不能放在等式左边,运行时会出错,2023/9/5446.4.1 字符串处理的两种方式指针常量,2024/8/29,45,6.4.2,字符串操作函数,实参数:字符数组名、已经初始化的字符指针,字符串常量,目的串必须是可写的。,2023/9/5456.4.2 字符串操作函数 实参数:字,2024/8/29,46,例6.14,strcpy,和,strncpy,的比较。,#include ,void main(), int n;,char *array1 = Happy Birthday to You;,char array3 15 ; char array2 25 ;,strcpy( array2, array1 );,cout The string in array1 is: array1, nThe string in array2 is: array2 n;,/*strcpy(array3,array1);,coutarray3endl; */,n=sizeof(array3);,strncpy( array3, array1, n-1 ); /,复制,array1,的,n-1,个字符,array3 14 = 0; /,添加,0,到,array3,cout The string in array3 is: array3 endl;,不包括提示的运行结果,Happy Birthday to You,Happy Birthday to You,Happy Birthday,复制,array1,到,array2,,没有问题,复制,array1,到,array3,,空间不够,有运行错误,按实际数组大小,复制,array1,到,array3,,没有问题,2023/9/546 例6.14 strcpy和strncp,2024/8/29,47,6.5,通过指针访问数组,2023/9/5476.5 通过指针访问数组,2024/8/29,48,6.5 通过指针访问数组,指针和数组有天然的联系,数组名就是地址,,也就是某种类型的指针,虽然一维数组名和二维数组名都是地址,都可以看作是某种指针,但是指针的类型是不同的,通过指针访问一维数组和二维数组的方法是不同的,2023/9/5486.5 通过指针访问数组指针和数组有天然,2024/8/29,49,6.5.1 通过指针访问一维数组,必须声明和数组类型相同的指针,并用数组名初始化指针:,int A10, *pa=A;,多种方式访问数组元素,数组名和下标,如,A0、A4,指针和下标,如,pa0、pa4,指针加偏移量的间接引用,如,*(pa+4),数组名加偏移量的间接引用,如,*(A+4),指针自加后的间接引用,如,*,pa+,2023/9/5496.5.1 通过指针访问一维数组必须声明,2024/8/29,50,例6.15 求数组内所存放的字符串的长度,void main(),char ChArray=This is a string.,*ptch;,int i,j,k,offset1,offset2;,ptch=ChArray;,/,指针初始化,for(i=0;,ChArrayi,!=0;i+);,coutThe length of the string is:iendl;,for(j=0;,ptchj,!=0;j+);,coutThe length of the string is:jendl;,for(offset1=0;,*(ChArray+offset1),!=0;offset1+);,coutThe length of the string is:offset1endl;,for(offset2=0;,*(ptch+offset2),!=0;offset2+);,coutThe length of the string is:offset2endl;,for(k=0;,*ptch+,!=0;k+);,coutThe length of the string is:kendl;,运行结果都相同,方式1,数组名下标,方式2:指针和下标,方式3: 数组名加偏移量的间接引用,方式4:指针加偏移量的间接引用,方式5:指针自加的间接引用,2023/9/550 例6.15 求数组内所存放的字符串的长,2024/8/29,51,例6.16求整型数组的平均值,显示数组元素和平均值。,void main(), int intArray10=8,11,23,34,45,56,65,78,86,97,*ptint;,int i,num,sum; float average;,ptint=intArray;,sum=0;,num=sizeof(intArray)/sizeof(*intArray);,for(i=0;inum;i+),sum=sum+*ptint+;,average=(float)sum/num;,ptint=intArray;,cout,数组元素是:,n;,for(i=0;inum;i+),cout*ptint+ ;,cout,“,n,平均值是:,”,averageendl;,运行结果:,数组元素是:,8 11 23 34 45 56 65 78 86 97,平均值是:,50.3,指针初始化,求数组元素的数目,求平均值,指针再次初始化,输出数组元素和它们的平均值,2023/9/551 例6.16求整型数组的平均值,显示数组,2024/8/29,52,6.5.2 通过指针访问二维数组,二维数组可以看成是一维数组的一维数组,二维数组名也是地址(指针),但和一维数组名有不同的类型,对一维数组,A5,数组名,A,的地址,是第一个元素,A0,的地址,指针的类型是指向数组元素的指针,A+1 A1,的地址,2023/9/5526.5.2 通过指针访问二维数组二维数组,2024/8/29,53,6.5.2 通过指针访问二维数组,对二维数组,B34,数组名,B,的地址,一维数组,B0,的地址,指针的类型是指向一维数组的指针,B+1,一维数组,B1,的地址,2023/9/5536.5.2 通过指针访问二维数组对二维数,2024/8/29,54,6.5.2 通过指针访问二维数组,定义指向一维数组的指针时,必须指出一维数组的大小,声明格式如下:,类型名 (*指针变量名)一维数组大小;,例如:,char (*ptchb)4, (*ptchc)2;,ptchb=B; ptchc=C;,2023/9/5546.5.2 通过指针访问二维数组定义指向,2024/8/29,55,6.5.2 通过指针访问二维数组,指向一维数组的指针具有的,特征,:,二维数组名是指向一维数组的指针,不指向数组元素,指针加,1,是指向下一个一维数组的指针,指向一维数组的指针的间接引用的结果仍然是地址,,即,*,ptchb,仍然是地址,为一维数组,B0,第一个元素,B00,的地址,*,ptchb,是数组元素的地址,,*,ptchb,就是数组元素的值,访问二维数组第,i,行第,j,列元素,:,*(*(,指针名,+,i)+j),2023/9/5556.5.2 通过指针访问二维数组指向一维,2024/8/29,56,例6.17比较指向一维数组的指针和指向数组元素的指针,void main(), short B34, C32;,short (*ptshb)4, (*ptshc)2;,ptshb=B; ptchc=C;,cout,比较不同的指向一维数组指针的差别,n;,coutptshb,的地址是:,ptshbn;,coutptshb+1,的地址是:,ptshb+1n;,coutptchc,的地址是:,ptshcn;,coutptchc+1,的地址是:,ptshc+1n;,比较不同的指向一维数组指针的差别,ptshb,的地址是:,0,x0012FF68,ptchb+1,的地址是:,0,x0012FF70,ptchc,的地址是:,0,x0012FF5C,ptchc+1,的地址是:,0,x0012FF60,B,的第0行地址,B,的第1行地址,C,的第0行地址,C,的第1行地址,2023/9/556 例6.17比较指向一维数组的指针和指向,2024/8/29,57,cout,不同类型的指针,n;,coutptshb,的地址是:,ptshbendl;,cout*ptshb,的地址是:,*,ptshbendl;,cout*ptshb+1,的地址是:,*,ptshb+1endl;,coutB01,的地址是:,&,B01endl;,/cout,“,ptchb,和,*,ptchb,相等吗?,”,(,ptchb=*ptchb)endl; /,有语法错误,类型不同,cout*ptshb+1,和,&,B01,相等吗?,;,if(*ptshb+1=,不同类型的指针,ptshb,的地址是:,0,x0012FF68,*ptshb,的地址是:,0,x0012FF68,*ptshb+1,的地址是:,0,x0012FF6A,B01,的地址是:,0,x0012FF6A,*ptshb+1,和,&,B01,相等吗?,Yes,B,的第0行地址,B,的第0行第0列 元素的地址,B,的第0行第1列 元素的地址,B,的第0行第1列 元素的地址,2023/9/557 cout不同类型的指针n,2024/8/29,58,例6.18 用单循环程序,求二维数组元素的平均值。,void main(),int Array34,=32,42,12,25,56,76,46,53,76,89,96,82,(*pt)4;,int sum, j;,float average;,sum=0;,pt=Array;,j=sizeof(Array) / sizeof (*Array);,for(int i=0;ij;i+),sum=sum+*(*pt+i);,average=(float)sum/j;,cout,数据的平均值等于:,averageendl;,运行结果:,数据的平均值等于57.0833,指向一维数组指针的初始化,求数组元素的数目,,*Array,就是元素,Array00,数组求和,求平均值,输出平均值,2023/9/558 例6.18 用单循环程序,求二维数组元,2024/8/29,59,一维数组:,int intArray2=8,11,*ptint;,sum=sum+*ptint+;,二维数组:,int A23,=32,42,12,25,56,76,(*pt)3;,sum=sum+*(*(pt+i)+j);,2023/9/559一维数组:,2024/8/29,60,6.6,指针访问动态内存,2023/9/5606.6 指针访问动态内存,2024/8/29,61,6.6 指针访问动态内存,动态内存,:,在程序执行时才可以申请、使用和释放的内存,存放动态数据的区域称为,“,堆,”,,动态内存也称为,堆内存,动态内存不能通过变量名来使用,只能通过指针来使用,2023/9/5616.6 指针访问动态内存 动态内存:,2024/8/29,62,6.6.1 动态内存的申请和释放,C+,中通过运算符,new,申请动态内存,运算符,delete,释放动态内存,new,的使用格式:,new,类型名 (初值),int *p;,p = new int(3);,申请成功: 返回指定类型内存的地址,申请失败,:,返回,NULL,指针,2023/9/5626.6.1 动态内存的申请和释放C+中,2024/8/29,63,6.6.1 动态内存的申请和释放,运算符,delete,释放动态内存,delete,运算符使用格式:,delete,指针名;,delete p ;,new,与,delete,应该成对出现,2023/9/5636.6.1 动态内存的申请和释放运算符d,2024/8/29,64,6.6.2 动态数组空间的申请和释放,申请动态数组要加上数组的大小:,一维:,new,类型名常量表达式 ;,注意:动态申请数组空间时,不可以对数组进行初始化,二维:,int (*pi_marray)4;,pi_marray = new int34;,释放动态数组空间都用相同的表达式:,delete ;,2023/9/5646.6.2 动态数组空间的申请和释放申请,2024/8/29,65,6.6.3,内存泄漏和指针悬挂,内存泄漏,动态申请的内存空间,没有正常释放,但也不能继续使用的情况。如:,char *ch1;,ch1 = new char(A);,char *ch2 = new char;,ch1=ch2;,原来为,ch1,所申请的存放字符,A,的空间就不能再使用了,产生了内存泄漏,2023/9/5656.6.3 内存泄漏和指针悬挂 内存泄漏,2024/8/29,66,6.6.3,内存泄漏和指针悬挂,指针指向一个已经释放的空间,即指针悬挂,char *ch1, *ch2;,ch1 = new char;,ch2 = ch1;,*ch2 = B;,delete ch1;,指针,ch2,指向了一个已经释放的地址空间,-,指针悬挂,用,delete ch2;,语句来释放,ch2,所指向的空间,会出现运行错误,2023/9/5666.6.3 内存泄漏和指针悬挂指针指向一,2024/8/29,67,6.7,引用概念,2023/9/567 6.7 引用概念,2024/8/29,68,6.7,引用概念,引用(,Reference,),是,C+,中新引入的概念,是,C,语言中不存在的数据类型,引用是,变量或者其他编程实体(如对象)的,别名,因此引用不可以单独定义,如图,6.4(,a),:变量,A,在内存中有自己的地址,而,A,的引用,B,实际上就是变量,A,,,只是,A,的另外一个名字,2023/9/5686.7 引用概念引用(Reference,2024/8/29,69,6.7.1,引用的声明和使用,引用通过运算符&来定义:,类型名 ,变量名必须已经定义,和引用的类型必须相同,int someInt;,int ,必须注意:引用必须在声明的时候就完成初始化,不可以先声明引用,然后再用另一个语句对它初始化。,2023/9/5696.7.1 引用的声明和使用引用通过运算,2024/8/29,70,改进,C,中函数的形参定义为指针型参数时所带来的不安全性,int add( int *x, int *y ),*x=*x+*y;,return *x;,int add( int &x, int &y ),x = x+y;,return x;,改为,2023/9/570改进C中函数的形参定义为指针型参数时所带,2024/8/29,71,6.7.1,引用的声明和使用,引用的特点:,引用不能独立存在,它只是其他变量的别名,引用必须在声明的同时初始化,引用一旦定义,引用关系就不可以更改,B,是,A,的引用,就不可能是其他变量的引用,引用的类型就是相关的变量的类型,引用的使用和变量的使用相同,2023/9/5716.7.1 引用的声明和使用引用的特点:,2024/8/29,72,例,6.22,引用的使用。观察以下程序的结果。,void main(),int intA=10;,int ,cout,“,引用的值和,相关变量值相同,:,refA=,refAendl;,refA=5;,cout,“,引用的变化,则相关变量也变化:,intA=,intAendl;,cout,“,引用的地址和相关变量地址相同:,intA,的地址,&,intAendl;,cout,“,引用的地址和相关变量地址相同:,refA,的地址,&,refAendl;,引用的值和相关变量值相同,:,refA=10,引用的变化,则相关变量也变化:,intA=5,引用的地址和相关变量地址相同:,intA,的地址,0,x0012FF7C,引用的地址和相关变量地址相同:,refA,的地址,0,x0012FF7C,2023/9/572 例6.22 引用的使用。观察以下程序的,2024/8/29,73,例6.23 指针的引用。,void main(),int intA=10,intB=20;,int *pti=,int *,cout,“,指针的引用可以访问指针所指的变量,:*,refi,=*refiendl;,cout,指针变量原来的值:,pti,=ptiendl;,refi=,cout,“,引用的变化,则相关指针也变化:,pti,=ptiendl;,cout,指针所指的变量值也发生变化:,*,pti,*ptiendl;,指针的引用可以访问指针所指的变量,:*,refi=10,指针变量原来的值,:,pti=0x0012FF7C,引用的变化,则相关指针也变化,:,pti=0x0012FF78,指针所指的变量值也发生变化:,*,pti,20,2023/9/573 例6.23 指针的引用。 指针的引用可,2024/8/29,74,6.7.1,引用的声明和使用,如果不希望通过引用来改变相关的变量的值,可以定义常引用:,const,类型名 ,例如:,int someInt = 10;,const int ,const_refA,就是常引用。不可以通过,const_refA,来改变,someInt,变量的值,2023/9/5746.7.1 引用的声明和使用如果不希望通,2024/8/29,75,6.7.2 通过,引用传递函数参数,引用,使用最多的场合是,作为,函数的,形式参数,引用作为函数的形参有以下,特点,:,形参,实参是相同类型的,变量,引用作为形参,参数传递属于,地址传递,引用作为形参,在函数中并不产生实参副本,是,同一个实体,函数对引用的操作,也是对实参变量的操作,函数调用可以改变实参数的值,2023/9/5756.7.2 通过引用传递函数参数引用使用,2024/8/29,76,例6.24 用引用作为形式参数,交换两个实参数。,#include ,using namespace std;,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=54321,函数调用后,:,a=54321 b=12345,2023/9/576 例6.24 用引用作为形式参数,交换两,2024/8/29,77,函数返回多个值 (可以用地址,还可用引用),float Length( int r ),return 2*PI*r;,float Area( int r),return PI*r*r;,给定半径,计算面积、周长,Void CalculateCircle( int r, float &length, float & area), length=2*PI*r;,area=PI*r*r; ,main(),int r=10; float l, s;,CalculateCircle(r, l, s);,2023/9/577函数返回多个值 (可以用地址,还可用,2024/8/29,78,6.7.2 通过,引用传递函数参数,使用引用作为形式参数还需要,注意,:,如果实参数需要保护,使用,“,常引用,”,作为形参,用引用作形参和用变量作形参是有区别的,尽管实参数可能相同,函数,swap(int a, int b),和,swap(int &a, int&b),看起来是两个可以区分的重载函数,但调用相同,: swap(x, y),,无法区分,函数,swap(int a, int b),和,swap(int &a, int&b),不是可以区分的重载函数,2023/9/5786.7.2 通过引用传递函数参数使用引用,2024/8/29,79,6.7.3 用,引用作为函数的返回值,返回引用需,注意,:,返回引用需在函数的返回值类型中加以说明,类型名 &函数名(形式参数表),返回引用的返回语句是:,return,变量名;,返回引用实际是返回地址,在使用上,或者直接使用这个地址;或者使用这个地址单元的数据,返回的引用可以作为左值继续操作,而返回的变量值是不可以继续运算的。这是返回引用和返回变量值在使用上的主要区别。,2023/9/5796.7.3 用引用作为函数的返回值返回引,2024/8/29,80,例6.25 引用作为函数返回值。,#include ,using namespace std;,int ,void main(),int pa=10,pb;,cout,输出,1,:,pb=,(pb=fun(pa)endl;,int ,cout,输出,2,:,pc=pcendl;,cout,输出,3,:,+,fun(pa)endl;,int &fun(int &pf),pf=pf+10;,coutpfendl;,return pf;,返回引用的函数原型,使用返回引用的变量值,使用返回引用的地址,返回的引用继续加,1,返回引用的函数,20,输出,1,:,pb=20,30,输出,2,:,pc=30,40,输出,3,:,41,2023/9/580 例6.25 引用作为函数返回值。返回引,2024/8/29,81,总结,指针变量的特点是可变性,即一个指针变量内的地址是可变的。所以,通过一个指针变量,就可以访问一个数组。,引用的特点是不变性,一个变量的引用就只能和这个变量联系在一起。,本章还介绍了函数调用的另一种方式:地址调用。具体又分为指针调用和引用调用。,2023/9/581总结指针变量的特点是可变性,即一个指针变,
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > PPT模板库


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!