《C++大学基础教程第六章课件.ppt》由会员分享,可在线阅读,更多相关《C++大学基础教程第六章课件.ppt(81页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、2023/1/11C+大学基础教程第第6章章 指针和引用指针和引用 2023/1/12指针(指针(PointerPointer)是)是C+C+和和C C的一的一种数据类型。很多其他高级语种数据类型。很多其他高级语言也有类似的数据类型。言也有类似的数据类型。引用(引用(ReferenceReference)则是)则是C+C+所所特有的一种数据类型。特有的一种数据类型。2023/1/13第六章第六章 指针和引用指针和引用6.1 指针的概念 6.2 指针的运算 6.3 指针和函数 6.4 指针和字符串 6.5 通过指针访问数组 6.6 指针访问动态内存6.7 引用概念 2023/1/146.1 6.
2、1 指针的概念指针的概念2023/1/156.1.1 指针和指针变量指针和指针变量指针是变量的地址地址例如,定义整型变量a,a的地址就是 一个指针。直接指定内存某个地址开始(如 0 x00430100)存放指针的变量就是指针变量。2023/1/166.1.1 指针和指针变量指针和指针变量当声明了一个指针变量后,确定了三件事:1.变量本身在内存中所分配的地址和字节数(4个)2.系统允许的地址范围,及地址单元内可以存放的内容3.指针变量可以进行的运算访问指针变量时,只能看到地址通过这个地址访问地址单元中的内容,这样的访问称为对于内存单元的间接访问。2023/1/176.1.2 指针变量的声明和初始
3、化指针变量的声明和初始化 指针变量声明的格式是:类型名*变量名1,*变量名2;例如:int*va1,*va2;char*ch1,*ch2;指针变量在声明后,变量的值(地址)是随机的。这样的指针变量是不能安全的使用的2023/1/186.1.2 指针变量的声明和初始化指针变量的声明和初始化 在声明指针变量时的“*”,有两个含义:声明变量va1、ch1、ch2都是指针变量;说明变量va1的类型是(int*)型,即指向整型变量的指针。ch1和ch2的类型是(char*)型指针变量都是有类型的-所指定的地址单元中存放的数据的类型 2023/1/196.1.2 指针变量的声明和初始化指针变量的声明和初始
4、化 指针变量必须初始化后才能安全使用声明指针变量时进行初始化的格式:类型名*指针变量名=&变量名;char ch1=Y,ch2=A;char*pch1=&ch1,*pch2=&ch2;2023/1/1106.1.2 指针变量的声明和初始化指针变量的声明和初始化 赋值方式进行初始化:int i1=Y,i2=A;int*pi1,*pi2;pi1=&i1;pi2=&i2;没有初始化的指针变量不可以使用 (编译系统会给出警告,而运行时会出现错误)2023/1/1116.2 6.2 指针的运算指针的运算 2023/1/1126.2 指针的运算指针的运算 表6.1 指针的运算2023/1/1136.2.1
5、 指针的赋值运算指针的赋值运算 指针的赋值:地址的赋值地址的赋值同类型变量的地址同类型的已经初始化的指针变量;其他同类型的指针用0或者NULL赋值“空指针”,即不指向任何的内存物理地址不同类型的指针不可以互相赋值不同类型的指针不可以互相赋值在指针赋值时,不存在类型自动转换的机制2023/1/114 例6.1 观察以下指针赋值运算的结果。如果将注释去掉,结果将如何?#include using namespace std;void main()int va1=100,*pva1;int*pva2=NULL;float vf1=A,*pvf1,*pvf2;coutvalue of pva2 is
6、pva2endl;pva1=&va1;pvf1=pvf2=&vf1;coutpva1&va1endl;coutpvf1 pvf2endl;/pvf1=pva1;value of pva2 is 0 x000000000 x0012FF7C 0 x0012FF7C0 x0012FF74 0 x0012FF74 注释去掉会出现编译错误注释去掉会出现编译错误2023/1/1156.2.2 间接引用运算间接引用运算 间接引用运算符“*”:一元运算符和指针变量连用,对指针所指向的内存地址单元进行间接访问使用的格式:*指针变量 如果指针变量iptr指向整型变量va*iptr就是变量va的内容 2023/1
7、/116 例6.2 对变量的直接访问和间接访问#include using namespace std;void main()char ch1=a,*ch;int k1=100;ch=&ch1;/指针ch指向变量ch1 cout*ch=*chendl;/间接访问 *ch=B;coutch1=ch1endl;/直接访问 ch1=k1;cout*ch=*chendl;/间接访问 运行结果运行结果:*ch=ach1=B*ch=d2023/1/117 例6.3 观察对这种指针变量间接访问的结果。#include using namespace std;void main()int va=100,*pv
8、a,*ppva;/ppva是指向指针的指针 int k1=100;pva=&va;cout*pva=*pvaendl;/间接访问结果是整型数 ppva=&pva;cout*ppva=*ppvaendl;/间接访问结果是地址 coutpva=pvaendl;/就是指针pva的内容运行结果运行结果:*pva=100*ppva=0 x0012FF7C pva=0 x0012FF7C 2023/1/1186.2.2 间接引用运算间接引用运算2023/1/1196.2.3 指针的算术运算指针的算术运算 可以进行的只有加法和减法加法和减法-和整数n做加法或者减法指针指针p p和整数和整数n n相相加加(相
9、减相减)的含义的含义是指向当前指向是指向当前指向位置位置p p的前方或的前方或后方第后方第n n个数据个数据的地址。的地址。2023/1/120 例6.4 通过指针的间接访问,输出下标为偶数的数组元素的值。#include using namespace std;void main()int k110=11,24,37,44,58,66,79,86,93,108,*k;k=&k10;for(int i=0;i10;i=i+2)coutk1i=*(k+i);coutendl;运行结果运行结果:K10=11 k12=37.数组第一个元素(下标为数组第一个元素(下标为0)的地址赋值给指针)的地址赋值
10、给指针k 每次循环,指针加每次循环,指针加2 22023/1/1216.2.3 指针的算术运算指针的算术运算指针和指针的直接加法没有意义直接加法没有意义指针和指针的减法可以减法可以进行-求出两个指针之间可以存放几个指定类型的数据不允许用一个整数减一个指针 2023/1/1226.2.4指针的关系运算和逻辑运算指针的关系运算和逻辑运算 同类型的指针可以可以进行关系运算进行指针“大于”、“小于”的比较,是判定指针在内存中的相对位置 指针和一般的整数比较没有意义,也不允许惟一可以和指针比较的整数是0。判定指针是不是空指针 2023/1/1236.2.5 void类型指针类型指针 void类型的指针就
11、是“无类型”指针:void*指针名;存放的也是内存的地址,但不指定这个地址单元内的数据的类型 2023/1/1246.2.5 void类型指针使用要点类型指针使用要点-任何指针都可以赋值给void指针 赋值后的void指针的类型仍然是void -void指针不可以赋值给其他任何类型的指针-void指针不可通过间接引用访问内存中数据-必须进行指针类型的强制转换,才可以使用指针间接引用访问内存数据 2023/1/125 例6.5 使用memcpy通用复制函数复制数组原型 void*memcpy(void*dest,const void*,size)#include using namespace
12、std;#include#include void main()void main()char src10=012345678;char src10=012345678;char dest10;char dest10;char*pc=(char*)memcpy(dest,src,10);char*pc=(char*)memcpy(dest,src,10);cout pc endl;cout pc endl;int s13=1,2,3;int s13=1,2,3;int d13;int d13;int*pi=(int*)memcpy(d1,s1,12);int*pi=(int*)memcpy(d
13、1,s1,12);cout*pi *(pi+1)*(pi+2)endl;cout*pi *(pi+1)*(pi+2)endl;运行结果运行结果:0123456780123456781 2 3 复制字符数据,复制字符数据,1010个个字节字节复制整型数据,复制整型数据,1212个个字节字节2023/1/1266.2.5 void类型指针类型指针 void类型指针应用:显示字符指针的内容其他指针直接用cout语句输出地址值而字符指针输出的是字符串将字符指针强制转换为void指针cout语句输出便是地址值例:char*pch=Hello C+;coutpchendl;cout(void*)pchen
14、dl;2023/1/127指针是地址int*p;p=&a;*p=100;b=*p+2;2023/1/1286.3 6.3 指针和函数指针和函数 2023/1/1296.3 指针和函数指针和函数在程序设计中,指针有很多应用其中之一就是作为函数的参数,形成了C+函数调用中的另一种调用方式:地址调用地址调用 2023/1/1306.3.1 指针作为函数的参数指针作为函数的参数实现地址调用,必须满足以下条件:函数的形式参数是指针变量形式参数是指针变量;函数的实参数是内存的地址实参数是内存的地址(可以是数组名数组名、变量的地址变量的地址、用变量地址初始化的指针指针)形参指针类型和实参地址类型必须相同类型
15、必须相同 2023/1/1316.3.1 指针作为函数的参数指针作为函数的参数实参传递给形参的是内存的地址,所以形参指针指向实参变量 形参指针通过间接引用,直接访问实参直接访问实参变量变量 (包括改变实参变量的值)函数调用后,改变了实参,如果有多个实参,就可以有多个实参变量在函数调用中被修改 2023/1/132 例6.6 编写数据交换的函数。#includevoid Swap(int*a,int*b);void Swap(int*a,int*b);void main()void main()int x(5),y(10);int x(5),y(10);coutcout主函数变量的值:主函数变量
16、的值:x=x y=yendl;x=x y=yendl;Swap(&x,&y);Swap(&x,&y);coutcout返回后变量的值:返回后变量的值:x=x y=yendl;x=x y=yendl;void Swap(int*a,int*b)void Swap(int*a,int*b)int t;int t;t=*a;t=*a;*a=*b;*a=*b;*b=t;*b=t;cout cout函数中完成了交换:函数中完成了交换:*a=*a *b=*bendl;a=*a *b=*bendl;运行结果运行结果:主函数变量的值:主函数变量的值:x=5 y=10函数中完成了交换:函数中完成了交换:*a=1
17、0 *b=5返回后变量的值:返回后变量的值:x=10 y=5 变量的地址作为实参数变量的地址作为实参数指针变量作为形式参数指针变量作为形式参数2023/1/1336.3.1 指针作为函数的参数指针作为函数的参数变量x和y的地址作实参传递给指针a和b,如图(a)通过间接引用*a和*b进行交换,实际上就是x和y进行交换,如图(b)2023/1/134 例6.7 指针变量指向一个数组#includeusing namespace std;void Move(int*a);void Move(int*a);void main()void main()int x5=10,20,30,40,50,*px=
18、x;int x5=10,20,30,40,50,*px=x;coutcout调用前的调用前的*px=*pxendl;px=*pxendl;Move(px);Move(px);coutcout调用后的调用后的px;px;if(px=x)coutif(px=x)cout没有变化,没有变化,*pxpx还是还是*pxendl;pxendl;else coutelse cout也向前移动,也向前移动,*pxpx变为变为*pxendl;pxendl;void Move(int*a)void Move(int*a)a=a+1;*a=100;a=a+1;*a=100;cout cout“函数中完成了指针函数中
19、完成了指针移动:移动:*a=*aendl;a=*aendl;运行结果运行结果:调用前的调用前的*px=10 函数中完成了指针移动:函数中完成了指针移动:*a=20 调用后的调用后的pxpx没有变化没有变化*px还是还是10 指针作为实参数指针作为实参数指针变量作为形式参数指针变量作为形式参数2023/1/1356.3.3 传递参数的保护传递参数的保护:指针和常量指针和常量 通过数组名地址调用,可以可以改变实参数组内容但有时并不需要改变数组的值 例如,在调用一个求数组最大值的函数时,就不希望数组的值发生变化 希望在函数中能够限制对数组元素的修改使用常指针可以达到这个目的 2023/1/1366.
20、3.3 传递参数的保护传递参数的保护:指针和常量指针和常量 常指针常指针是指向常量的指针(Pointer to Constant data)规定指针所指向的内容不可以通过指针的规定指针所指向的内容不可以通过指针的间接引用来改变间接引用来改变。常指针说明的格式是:const 类型名*指针名;例如:const int*ptint;指针ptint的类型是(const int*),即指向一个恒定的整型数 2023/1/137 例6.10 常指针示例。观察以下程序的运行。#include using namespace std;void main()void main()int ia=10,ib=20;
21、int ia=10,ib=20;const int*ptint;const int*ptint;ptint=&ia;ptint=&ia;/用用ia ia地址初始化地址初始化cout*ptintendl;cout*ptintendl;ptint=&ib;ptint=&ib;/改变为改变为ib ib的地址的地址ib=ib+100;ib=ib+100;/ib/ib本身仍然可以改变本身仍然可以改变cout*ptintendl;cout*ptintendl;/*ptint=100;/*ptint=100;/语句错误:左值是常量语句错误:左值是常量 运行结果运行结果:10 120 常指针声明常指针声明注释
22、去掉会出现编译错误注释去掉会出现编译错误2023/1/1386.3.3 传递参数的保护传递参数的保护:指针和常量指针和常量 指针常量指针常量(Pointer constant)指针本身是常量指针本身是常量(地址是常量地址是常量),不可以改变指针常量声明的格式:类型名类型名*const 指针名指针名=初值初值;char ch,*const ptch=&ch;数组名是数组的首地址-数组名是指针常量 2023/1/139 例6.11 指针常量示例。指出以下程序的错误。#include using namespace std;void main()int a=10,b=100;int*const pa
23、=&a;int*const pa=&a;/pa是指针常量 cout*paendl;*pa=20;*pa=20;/指针常量的间接引用是允许的 coutaendl;pa=&b;const int c=50;int*const pc=&c;错误语句注错误语句注释掉后运行释掉后运行结果结果:10 20 语句有错:常量不语句有错:常量不能当左值能当左值语句有错,地址语句有错,地址类型不同类型不同不能用常量地址不能用常量地址初始化指针常量初始化指针常量2023/1/140 例6.12 用常指针作形参,函数printString可以输出数组的内容,不可以对数组修改。#include using namesp
24、ace std;void printString(const char*);void printString(const char*);void main()void main()char phrase=C+is a programming language;char phrase=C+is a programming language;cout The string is:n;cout The string is:n;printString(phrase);cout endl;printString(phrase);cout endl;/main/main函数结束函数结束void print
25、String(const char*Ptarray)void printString(const char*Ptarray)while(*Ptarray)while(*Ptarray)cout *Ptarray+;cout *Ptarray+;不使用常指针也不使用常指针也是可以完成打印。是可以完成打印。但是没有保护了。但是没有保护了。数组名作实参数数组名作实参数常指针作形式参数常指针作形式参数2023/1/1416.4 6.4 指针和字符串指针和字符串 2023/1/1426.4.1 字符串处理的两种方式字符串处理的两种方式字符串常量字符串常量:双引号括起,0结束 如:This is a st
26、ring。字符串常量有自己固定的首地址 如果将字符串常量的首地址看成是指针,这种指针既是常指针,也是指针常量。2023/1/1436.4.1 字符串处理的两种方式字符串处理的两种方式处理字符串两种方式:数组方式数组方式和指针方式指针方式 数组方式数组方式是将字符串存入字符数组:char string_array=Whats a nice day!;指针方式指针方式是用字符串常量来初始化一个字符指针:char*string_pt=Whats a nice day!;2023/1/1446.4.1 字符串处理的两种方式字符串处理的两种方式指针常量不能指针常量不能放在等式左边放在等式左边运行时会出运
27、行时会出错错2023/1/1456.4.2 字符串操作函数字符串操作函数 实参数:字符数组名、已经初始化的字符指针,字符串常量实参数:字符数组名、已经初始化的字符指针,字符串常量目的串必须是可写的。目的串必须是可写的。2023/1/146 例6.14 strcpy和strncpy的比较。#include#include void main()void main()int n;int n;char*array1=Happy Birthday to You;char*array1=Happy Birthday to You;char array3 15;char array2 25;char ar
28、ray3 15;char array2 25;strcpy(array2,array1);strcpy(array2,array1);cout The string in array1 is:array1 cout The string in array1 is:array1 nThe string in array2 is:array2 n;nThe string in array2 is:array2 n;/*strcpy(array3,array1);/*strcpy(array3,array1);coutarray3endl;*/coutarray3endl;*/n=sizeof(ar
29、ray3);n=sizeof(array3);strncpy(array3,array1,n-1);/strncpy(array3,array1,n-1);/复制复制array1array1的的n-1n-1个字符个字符 array3 14 =0;/array3 14 =0;/添加添加0 0 到到array3array3 cout The string in array3 is:array3 endl;cout The string in array3 is:array3 endl;不包括提示的运行结果不包括提示的运行结果Happy Birthday to YouHappy Birthday t
30、o YouHappy Birthday 复制复制array1array1到到array2array2,没有问题没有问题复制复制array1array1到到array3array3,空间不够,空间不够,有运行错误有运行错误按实际数组大小,复制按实际数组大小,复制array1array1到到array3array3,没有问题没有问题2023/1/1476.5 6.5 通过指针访问数组通过指针访问数组 2023/1/1486.5 通过指针访问数组通过指针访问数组指针和数组有天然的联系数组名就是地址数组名就是地址,也就是某种类型的指针虽然一维数组名和二维数组名都是地址,都可以看作是某种指针,但是指针的
31、类型是不同的通过指针访问一维数组和二维数组的方法是不同的 2023/1/1496.5.1 通过指针访问一维数组通过指针访问一维数组必须声明和数组类型相同的指针,并用数组名初始化指针:int A10,*pa=A;多种方式访问数组元素多种方式访问数组元素1.数组名和下标,如A0、A4 2.指针和下标,如pa0、pa4 3.指针加偏移量的间接引用,如*(pa+4)4.数组名加偏移量的间接引用,如*(A+4)5.指针自加后的间接引用,如*pa+2023/1/150 例6.15 求数组内所存放的字符串的长度 void main()char ChArray=This is a string.,*ptch;
32、char ChArray=This is a string.,*ptch;int i,j,k,offset1,offset2;int i,j,k,offset1,offset2;ptch=ChArray;ptch=ChArray;/指针初始化指针初始化 for(i=0;for(i=0;ChArrayiChArrayi!=0;i+);!=0;i+);coutThe length of the string is:iendl;coutThe length of the string is:iendl;for(j=0;for(j=0;ptchjptchj!=0;j+);!=0;j+);coutThe
33、 length of the string is:jendl;coutThe length of the string is:jendl;for(offset1=0;for(offset1=0;*(ChArray+offset1)*(ChArray+offset1)!=0;offset1+);!=0;offset1+);coutThe length of the string is:offset1endl;coutThe length of the string is:offset1endl;for(offset2=0;for(offset2=0;*(ptch+offset2)*(ptch+o
34、ffset2)!=0;offset2+);!=0;offset2+);coutThe length of the string is:offset2endl;coutThe length of the string is:offset2endl;for(k=0;for(k=0;*ptch+*ptch+!=0;k+);!=0;k+);coutThe length of the string is:kendl;coutThe length of the string is:kendl;运行结果都相同运行结果都相同方式方式1 1数组名下标数组名下标方式方式2 2:指针和下标:指针和下标方式方式3 3
35、:数组名加数组名加偏移量的间接引用偏移量的间接引用方式方式4 4:指针加偏:指针加偏移量的间接引用移量的间接引用方式方式5 5:指针自加的间接引用:指针自加的间接引用2023/1/151 例6.16求整型数组的平均值,显示数组元素和平均值。void main()void main()int intArray10=8,11,23,34,45,56,65,78,86,97,*ptint;int intArray10=8,11,23,34,45,56,65,78,86,97,*ptint;int i,num,sum;float average;int i,num,sum;float average;
36、ptint=intArray;ptint=intArray;sum=0;sum=0;num=sizeof(intArray)/sizeof(*intArray);num=sizeof(intArray)/sizeof(*intArray);for(i=0;inum;i+)for(i=0;inum;i+)sum=sum+*ptint+;sum=sum+*ptint+;average=(float)sum/num;average=(float)sum/num;ptint=intArray;ptint=intArray;coutcout数组元素是:数组元素是:n;n;for(i=0;inum;i+)
37、for(i=0;inum;i+)cout*ptint+;cout*ptint+;cout cout“nn平均值是:平均值是:”averageendl;averageendl;运行结果:运行结果:数组元素是:数组元素是:8 8 11 11 23 23 34 34 45 45 56 56 65 65 78 86 9778 86 97平均值是:平均值是:50.3 指针初始化指针初始化求数组元素求数组元素的数目的数目求平均值求平均值指针再次初始化指针再次初始化输出数组元输出数组元素和它们的素和它们的平均值平均值2023/1/1526.5.2 通过指针访问二维数组通过指针访问二维数组二维数组可以看成是一
38、维数组的一维数组 二维数组名也是地址(指针),但和一维数组名有不同的类型对一维数组A5数组名A的地址,是第一个元素A0的地址指针的类型是指向数组元素的指针A+1 A1的地址 2023/1/1536.5.2 通过指针访问二维数组通过指针访问二维数组对二维数组B34数组名B的地址,一维数组B0的地址指针的类型是指向一维数组的指针指针的类型是指向一维数组的指针B+1 一维数组B1的地址 2023/1/1546.5.2 通过指针访问二维数组通过指针访问二维数组定义指向一维数组的指针时,必须指出一维数组的大小 声明格式如下:类型名(*指针变量名)一维数组大小;例如:char(*ptchb)4,(*ptc
39、hc)2;ptchb=B;ptchc=C;2023/1/1556.5.2 通过指针访问二维数组通过指针访问二维数组指向一维数组的指针具有的特征:二维数组名是指向一维数组的指针,不指向数组元素 指针加1 是指向下一个一维数组的指针 指向一维数组的指针的间接引用的结果仍然是地址,即*ptchb仍然是地址,为一维数组B0第一个元素B00的地址*ptchb是数组元素的地址,*ptchb就是数组元素的值访问二维数组第i行第j列元素:*(*(指针名+i)+j)2023/1/156 例6.17比较指向一维数组的指针和指向数组元素的指针 void main()short B34,C32;short(*ptsh
40、b)4,(*ptshc)2;ptshb=B;ptchc=C;cout比较不同的指向一维数组指针的差别n;coutptshb的地址是:ptshbn;coutptshb+1的地址是:ptshb+1n;coutptchc的地址是:ptshcn;coutptchc+1的地址是:ptshc+1n;比较不同的指向一维数组指针的差别比较不同的指向一维数组指针的差别ptshbptshb的地址是:的地址是:0 0 x0012FF68x0012FF68ptchb+1ptchb+1的地址是:的地址是:0 0 x0012FF70 x0012FF70ptchcptchc的地址是:的地址是:0 0 x0012FF5Cx0
41、012FF5Cptchc+1ptchc+1的地址是:的地址是:0 0 x0012FF60 x0012FF60 B B的第的第0 0行地址行地址 B B的第的第1 1行地址行地址 C C的第的第0 0行地址行地址 C C的第的第1 1行地址行地址2023/1/157 cout不同类型的指针n;coutptshb的地址是:ptshbendl;cout*ptshb的地址是:*ptshbendl;cout*ptshb+1的地址是:*ptshb+1endl;coutB01的地址是:&B01endl;/cout“ptchb和*ptchb相等吗?”(ptchb=*ptchb)endl;/有语法错误,类型不同
42、 cout*ptshb+1和&B01相等吗?;if(*ptshb+1=&B01)coutYesendl;不同类型的指针不同类型的指针ptshbptshb的地址是:的地址是:0 0 x0012FF68x0012FF68*ptshb*ptshb的地址是:的地址是:0 0 x0012FF68x0012FF68*ptshb+1*ptshb+1的地址是:的地址是:0 0 x0012FF6Ax0012FF6AB01B01的地址是:的地址是:0 0 x0012FF6Ax0012FF6A*ptshb+1*ptshb+1和和&B01B01相等吗?相等吗?YesYes B B的第的第0 0行地址行地址 B B的第
43、的第0 0行第行第0 0列列 元素的地址元素的地址 B B的第的第0 0行第行第1 1列列 元素的地址元素的地址 B B的第的第0 0行第行第1 1列列 元素的地址元素的地址2023/1/158 例6.18 用单循环程序,求二维数组元素的平均值。void main()int Array34int Array34=32,42,12,25,56,76,46,53,76,89,96,82,(*pt)4;(*pt)4;int sum,j;float average;sum=0;pt=Array;pt=Array;j=sizeof(Array)/sizeof(*Array);for(int i=0;ij
44、;i+)sum=sum+*(*pt+i);average=(float)sum/j;cout数据的平均值等于:averageendl;运行结果:运行结果:数据的平均值等于数据的平均值等于57.083357.0833指向一维数组指针的初始化指向一维数组指针的初始化求数组元素的数目,求数组元素的数目,*Array*Array就是元素就是元素Array00Array00数组求和数组求和求平均值求平均值输出平均值输出平均值2023/1/159一维数组:一维数组:int intArray2=8,11,*ptint;int intArray2=8,11,*ptint;sum=sum+*ptint+;sum
45、=sum+*ptint+;二维数组:二维数组:int A23int A23=32,42,12,25,56,76,(*pt)3;(*pt)3;sum=sum+*(*(pt+i)+j);sum=sum+*(*(pt+i)+j);2023/1/1606.6 6.6 指针访问动态内存指针访问动态内存2023/1/1616.6 指针访问动态内存指针访问动态内存 动态内存:在程序执行时才可以申请、使用和释放的内存存放动态数据的区域称为“堆”,动态内存也称为堆内存堆内存 动态内存不能通过变量名来使用,只能通过指针来使用 2023/1/1626.6.1 动态内存的申请和释放动态内存的申请和释放C+中通过运算符
46、new申请动态内存,运算符delete释放动态内存new的使用格式:new 类型名(初值)int*p;p=new int(3);申请成功:返回指定类型内存的地址申请失败:返回NULL指针2023/1/1636.6.1 动态内存的申请和释放动态内存的申请和释放运算符delete释放动态内存delete运算符使用格式:delete 指针名;delete p;new 与delete 应该成对出现2023/1/1646.6.2 动态数组空间的申请和释放动态数组空间的申请和释放申请动态数组要加上数组的大小:一维:一维:new 类型名常量表达式;注意:动态申请数组空间时,不可以对数组进行初始化二维:二维:
47、int(*pi_marray)4;pi_marray=new int34;释放动态数组空间都用相同的表达式:delete;2023/1/1656.6.3 内存泄漏和指针悬挂内存泄漏和指针悬挂 内存泄漏 动态申请的内存空间,没有正常释放,但也不能继续使用的情况。如:char*ch1;ch1=new char(A);char*ch2=new char;ch1=ch2;原来为ch1所申请的存放字符A的空间就不能再使用了,产生了内存泄漏 2023/1/1666.6.3 内存泄漏和指针悬挂内存泄漏和指针悬挂指针指向一个已经释放的空间,即指针悬挂 char*ch1,*ch2;ch1=new char;ch
48、2=ch1;*ch2=B;delete ch1;指针ch2指向了一个已经释放的地址空间-指针悬挂用用delete ch2;语句来释放语句来释放ch2所指向的空间,所指向的空间,会出现运行错误会出现运行错误2023/1/167 6.7 6.7 引用概念引用概念2023/1/1686.7 引用概念引用概念引用(Reference)是C+中新引入的概念,是C语言中不存在的数据类型 引引用用是是变量或者其他编程实体(如对象)的别别名名因此引用不可以单独定义如图6.4(a):变量A在内存中有自己的地址,而A的引用B实际上就是变量A,只是A的另外一个名字 2023/1/1696.7.1 引用的声明和使用引
49、用的声明和使用引用通过运算符&来定义:类型名&引用名=变量名;变量名必须已经定义变量名必须已经定义和引用的类型必须相同和引用的类型必须相同 int someInt;int&refInt=someInt;必须注意:引用必须在声明的时候就完成初始化,不可以先声明引用,然后再用另一个语句对它初始化。2023/1/170改进C中函数的形参定义为指针型参数时所带来的不安全性int add(int*x,int*y)*x=*x+*y;return*x;int add(int&x,int&y)x=x+y;return x;改为改为2023/1/1716.7.1 引用的声明和使用引用的声明和使用引用的特点:引用
50、不能独立存在,它只是其他变量的别名 引用必须在声明的同时初始化 引用一旦定义,引用关系就不可以更改B是A的引用,就不可能是其他变量的引用 引用的类型就是相关的变量的类型,引用的使用和变量的使用相同 2023/1/172 例6.22 引用的使用。观察以下程序的结果。void main()int intA=10;int&refA=intA;cout“引用的值和相关变量值相同:refA=refAendl;refA=5;cout“引用的变化,则相关变量也变化:intA=intAendl;cout“引用的地址和相关变量地址相同:intA的地址&intAendl;cout“引用的地址和相关变量地址相同:r