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

上传人:2127513****773577... 文档编号:241320751 上传时间:2024-06-17 格式:PPT 页数:81 大小:527.50KB
返回 下载 相关 举报
C++大学基础教程第六章课件_第1页
第1页 / 共81页
C++大学基础教程第六章课件_第2页
第2页 / 共81页
C++大学基础教程第六章课件_第3页
第3页 / 共81页
点击查看更多>>
资源描述
2024/6/171C+大学基础教程第第6章章 指针和引用指针和引用 2023/8/91C+大学基础教程第6章 指针和引用 2024/6/172指针(指针(PointerPointer)是)是C+C+和和C C的一的一种数据类型。很多其他高级语种数据类型。很多其他高级语言也有类似的数据类型。言也有类似的数据类型。引用(引用(ReferenceReference)则是)则是C+C+所所特有的一种数据类型。特有的一种数据类型。2023/8/92指针(Pointer)是C+和C的一种数2024/6/173第六章第六章 指针和引用指针和引用6.1 指针的概念 6.2 指针的运算 6.3 指针和函数 6.4 指针和字符串 6.5 通过指针访问数组 6.6 指针访问动态内存6.7 引用概念 2023/8/93第六章 指针和引用6.1 指针的概念 2024/6/1746.1 6.1 指针的概念指针的概念2023/8/946.1 指针的概念2024/6/1756.1.1 指针和指针变量指针和指针变量指针是变量的地址地址例如,定义整型变量a,a的地址就是 一个指针。直接指定内存某个地址开始(如 0 x00430100)存放指针的变量就是指针变量。2023/8/956.1.1 指针和指针变量指针是变量的地址2024/6/1766.1.1 指针和指针变量指针和指针变量当声明了一个指针变量后,确定了三件事:1.变量本身在内存中所分配的地址和字节数(4个)2.系统允许的地址范围,及地址单元内可以存放的内容3.指针变量可以进行的运算访问指针变量时,只能看到地址通过这个地址访问地址单元中的内容,这样的访问称为对于内存单元的间接访问。2023/8/966.1.1 指针和指针变量当声明了一个指针2024/6/1776.1.2 指针变量的声明和初始化指针变量的声明和初始化 指针变量声明的格式是:类型名*变量名1,*变量名2;例如:int*va1,*va2;char*ch1,*ch2;指针变量在声明后,变量的值(地址)是随机的。这样的指针变量是不能安全的使用的2023/8/976.1.2 指针变量的声明和初始化 指针变2024/6/1786.1.2 指针变量的声明和初始化指针变量的声明和初始化 在声明指针变量时的“*”,有两个含义:声明变量va1、ch1、ch2都是指针变量;说明变量va1的类型是(int*)型,即指向整型变量的指针。ch1和ch2的类型是(char*)型指针变量都是有类型的-所指定的地址单元中存放的数据的类型 2023/8/986.1.2 指针变量的声明和初始化 在声明2024/6/1796.1.2 指针变量的声明和初始化指针变量的声明和初始化 指针变量必须初始化后才能安全使用声明指针变量时进行初始化的格式:类型名*指针变量名=&变量名;char ch1=Y,ch2=A;char*pch1=&ch1,*pch2=&ch2;2023/8/996.1.2 指针变量的声明和初始化 指针变2024/6/17106.1.2 指针变量的声明和初始化指针变量的声明和初始化 赋值方式进行初始化:int i1=Y,i2=A;int*pi1,*pi2;pi1=&i1;pi2=&i2;没有初始化的指针变量不可以使用 (编译系统会给出警告,而运行时会出现错误)2023/8/9106.1.2 指针变量的声明和初始化 赋值2024/6/17116.2 6.2 指针的运算指针的运算 2023/8/9116.2 指针的运算 2024/6/17126.2 指针的运算指针的运算 表6.1 指针的运算2023/8/9126.2 指针的运算 2024/6/17136.2.1 指针的赋值运算指针的赋值运算 指针的赋值:地址的赋值地址的赋值同类型变量的地址同类型的已经初始化的指针变量;其他同类型的指针用0或者NULL赋值“空指针”,即不指向任何的内存物理地址不同类型的指针不可以互相赋值不同类型的指针不可以互相赋值在指针赋值时,不存在类型自动转换的机制2023/8/9136.2.1 指针的赋值运算 指针的赋值:2024/6/1714 例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=&va1;pvf1=pvf2=&vf1;coutpva1&va1endl;coutpvf1 pvf2endl;/pvf1=pva1;value of pva2 is 0 x000000000 x0012FF7C 0 x0012FF7C0 x0012FF74 0 x0012FF74 注释去掉会出现编译错误注释去掉会出现编译错误2023/8/914 例6.1 观察以下指针赋值运算的结果。2024/6/17156.2.2 间接引用运算间接引用运算 间接引用运算符“*”:一元运算符和指针变量连用,对指针所指向的内存地址单元进行间接访问使用的格式:*指针变量 如果指针变量iptr指向整型变量va*iptr就是变量va的内容 2023/8/9156.2.2 间接引用运算 间接引用运算符2024/6/1716 例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/8/916 例6.2 对变量的直接访问和间接访问运2024/6/1717 例6.3 观察对这种指针变量间接访问的结果。#include using namespace std;void main()int va=100,*pva,*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/8/917 例6.3 观察对这种指针变量2024/6/17186.2.2 间接引用运算间接引用运算2023/8/9186.2.2 间接引用运算2024/6/17196.2.3 指针的算术运算指针的算术运算 可以进行的只有加法和减法加法和减法-和整数n做加法或者减法指针指针p p和整数和整数n n相相加加(相减相减)的含义的含义是指向当前指向是指向当前指向位置位置p p的前方或的前方或后方第后方第n n个数据个数据的地址。的地址。2023/8/9196.2.3 指针的算术运算 可以进行的只2024/6/1720 例6.4 通过指针的间接访问,输出下标为偶数的数组元素的值。#includeusingnamespacestd;voidmain()intk110=11,24,37,44,58,66,79,86,93,108,*k;k=&k10;for(inti=0;i10;i=i+2)coutk1i=*(k+i);coutendl;运行结果运行结果:K10=11 k12=37.数组第一个元素(下标为数组第一个元素(下标为0)的地址赋值给指针)的地址赋值给指针k 每次循环,指针加每次循环,指针加22023/8/920 例6.4 通过指针的间接访问,输出下标2024/6/17216.2.3 指针的算术运算指针的算术运算指针和指针的直接加法没有意义直接加法没有意义指针和指针的减法可以减法可以进行-求出两个指针之间可以存放几个指定类型的数据不允许用一个整数减一个指针 2023/8/9216.2.3 指针的算术运算指针和指针的直2024/6/17226.2.4指针的关系运算和逻辑运算指针的关系运算和逻辑运算 同类型的指针可以可以进行关系运算进行指针“大于”、“小于”的比较,是判定指针在内存中的相对位置 指针和一般的整数比较没有意义,也不允许惟一可以和指针比较的整数是0。判定指针是不是空指针 2023/8/9226.2.4指针的关系运算和逻辑运算 同2024/6/17236.2.5 void类型指针类型指针 void类型的指针就是“无类型”指针:void*指针名;存放的也是内存的地址,但不指定这个地址单元内的数据的类型 2023/8/9236.2.5 void类型指针 void类2024/6/17246.2.5 void类型指针使用要点类型指针使用要点-任何指针都可以赋值给void指针 赋值后的void指针的类型仍然是void -void指针不可以赋值给其他任何类型的指针-void指针不可通过间接引用访问内存中数据-必须进行指针类型的强制转换,才可以使用指针间接引用访问内存数据 2023/8/9246.2.5 void类型指针使用要点-2024/6/1725 例6.5 使用memcpy通用复制函数复制数组原型 void*memcpy(void*dest,const void*,size)#includeusingnamespacestd;#includevoidmain()charsrc10=012345678;chardest10;char*pc=(char*)memcpy(dest,src,10);coutpcendl;ints13=1,2,3;intd13;int*pi=(int*)memcpy(d1,s1,12);cout*pi*(pi+1)*(pi+2)endl;运行结果运行结果:0123456781 2 3 复制字符数据,复制字符数据,1010个个字节字节复制整型数据,复制整型数据,1212个个字节字节2023/8/925 例6.5 使用memcpy通用复制函数2024/6/17266.2.5 void类型指针类型指针 void类型指针应用:显示字符指针的内容其他指针直接用cout语句输出地址值而字符指针输出的是字符串将字符指针强制转换为void指针cout语句输出便是地址值例:char*pch=Hello C+;coutpchendl;cout(void*)pchendl;2023/8/9266.2.5 void类型指针 void类2024/6/1727指针是地址int*p;p=&a;*p=100;b=*p+2;2023/8/927指针是地址int*p;*p=100;2024/6/17286.3 6.3 指针和函数指针和函数 2023/8/9286.3 指针和函数 2024/6/17296.3 指针和函数指针和函数在程序设计中,指针有很多应用其中之一就是作为函数的参数,形成了C+函数调用中的另一种调用方式:地址调用地址调用 2023/8/9296.3 指针和函数在程序设计中,指针有很2024/6/17306.3.1 指针作为函数的参数指针作为函数的参数实现地址调用,必须满足以下条件:函数的形式参数是指针变量形式参数是指针变量;函数的实参数是内存的地址实参数是内存的地址(可以是数组名数组名、变量的地址变量的地址、用变量地址初始化的指针指针)形参指针类型和实参地址类型必须相同类型必须相同 2023/8/9306.3.1 指针作为函数的参数实现地址调2024/6/17316.3.1 指针作为函数的参数指针作为函数的参数实参传递给形参的是内存的地址,所以形参指针指向实参变量 形参指针通过间接引用,直接访问实参直接访问实参变量变量 (包括改变实参变量的值)函数调用后,改变了实参,如果有多个实参,就可以有多个实参变量在函数调用中被修改 2023/8/9316.3.1 指针作为函数的参数2024/6/1732 例6.6 编写数据交换的函数。#includevoidSwap(int*a,int*b);voidmain()intx(5),y(10);cout主主函函数数变变量量的的值值:x=x y=yendl;Swap(&x,&y);cout返返回回后后变变量量的的值值:x=x y=yendl;voidSwap(int*a,int*b)intt;t=*a;*a=*b;*b=t;cout函函数数中中完完成成了了交交换换:*a=*a*b=*bendl;运行结果运行结果:主函数变量的值:主函数变量的值:x=5 y=10函数中完成了交换:函数中完成了交换:*a=10 *b=5返回后变量的值:返回后变量的值:x=10 y=5 变量的地址作为实参数变量的地址作为实参数指针变量作为形式参数指针变量作为形式参数2023/8/932 例6.6 编写数据交换的函数。运行结果2024/6/17336.3.1 指针作为函数的参数指针作为函数的参数变量x和y的地址作实参传递给指针a和b,如图(a)通过间接引用*a和*b进行交换,实际上就是x和y进行交换,如图(b)2023/8/9336.3.1 指针作为函数的参数变量x和y2024/6/1734 例6.7 指针变量指向一个数组#includeusingnamespacestd;voidMove(int*a);voidmain()intx5=10,20,30,40,50,*px=x;cout调用前的调用前的*px=*pxendl;Move(px);cout调用后的调用后的px;if(px=x)cout没没有有变变化化,*px还还是是*pxendl;elsecout也也 向向 前前 移移 动动,*px变变 为为*pxendl;voidMove(int*a)a=a+1;*a=100;cout“函数中完成了指针函数中完成了指针移动:移动:*a=*aendl;运行结果运行结果:调用前的调用前的*px=10 函数中完成了指针移动:函数中完成了指针移动:*a=20 调用后的调用后的pxpx没有变化没有变化*px还是还是10指针作为实参数指针作为实参数指针变量作为形式参数指针变量作为形式参数2023/8/934 例6.7 指针变量指向一个数组运行结果2024/6/17356.3.3 传递参数的保护传递参数的保护:指针和常量指针和常量 通过数组名地址调用,可以可以改变实参数组内容但有时并不需要改变数组的值 例如,在调用一个求数组最大值的函数时,就不希望数组的值发生变化 希望在函数中能够限制对数组元素的修改使用常指针可以达到这个目的 2023/8/9356.3.3 传递参数的保护:指针和常量 2024/6/17366.3.3 传递参数的保护传递参数的保护:指针和常量指针和常量 常指针常指针是指向常量的指针(Pointer to Constant data)规定指针所指向的内容不可以通过指针的规定指针所指向的内容不可以通过指针的间接引用来改变间接引用来改变。常指针说明的格式是:const 类型名*指针名;例如:const int*ptint;指针ptint的类型是(const int*),即指向一个恒定的整型数 2023/8/9366.3.3 传递参数的保护:指针和常量 2024/6/1737 例6.10 常指针示例。观察以下程序的运行。#includeusingnamespacestd;voidmain()intia=10,ib=20;constint*ptint;ptint=&ia;/用用ia地址初始化地址初始化cout*ptintendl;ptint=&ib;/改变为改变为ib的地址的地址ib=ib+100;/ib本身仍然可以改变本身仍然可以改变cout*ptintendl;/*ptint=100;/语句错误:左值是常量语句错误:左值是常量 运行结果运行结果:10 120 常指针声明常指针声明注释去掉会出现编译错误注释去掉会出现编译错误2023/8/937 例6.10 常指针示例。观察以下程序的2024/6/17386.3.3 传递参数的保护传递参数的保护:指针和常量指针和常量 指针常量指针常量(Pointer constant)指针本身是常量指针本身是常量(地址是常量地址是常量),不可以改变指针常量声明的格式:类型名类型名*const 指针名指针名=初值初值;char ch,*const ptch=&ch;数组名是数组的首地址-数组名是指针常量 2023/8/9386.3.3 传递参数的保护:指针和常量 2024/6/1739 例6.11 指针常量示例。指出以下程序的错误。#includeusingnamespacestd;voidmain()inta=10,b=100;int*constpa=&a;/pa是指针常量cout*paendl;*pa=20;/指针常量的间接引用是允许的coutaendl;pa=&b;constintc=50;int*constpc=&c;错误语句注错误语句注释掉后运行释掉后运行结果结果:10 20 语句有错:常量不语句有错:常量不能当左值能当左值语句有错,地址语句有错,地址类型不同类型不同不能用常量地址不能用常量地址初始化指针常量初始化指针常量2023/8/939 例6.11 指针常量示例。指出以下程序2024/6/1740 例6.12 用常指针作形参,函数printString可以输出数组的内容,不可以对数组修改。#includeusingnamespacestd;voidprintString(constchar*);voidmain()char phrase=C+is a programminglanguage;coutThestringis:n;printString(phrase);coutendl;/main函数结束函数结束voidprintString(constchar*Ptarray)while(*Ptarray)cout*Ptarray+;不使用常指针也不使用常指针也是可以完成打印。是可以完成打印。但是没有保护了。但是没有保护了。数组名作实参数数组名作实参数常指针作形式参数常指针作形式参数2023/8/940 例6.12 用常指针作形参,函数pri2024/6/17416.4 6.4 指针和字符串指针和字符串 2023/8/9416.4 指针和字符串 2024/6/17426.4.1 字符串处理的两种方式字符串处理的两种方式字符串常量字符串常量:双引号括起,0结束 如:This is a string。字符串常量有自己固定的首地址 如果将字符串常量的首地址看成是指针,这种指针既是常指针,也是指针常量。2023/8/9426.4.1 字符串处理的两种方式字符串常2024/6/17436.4.1 字符串处理的两种方式字符串处理的两种方式处理字符串两种方式:数组方式数组方式和指针方式指针方式 数组方式数组方式是将字符串存入字符数组:char string_array=Whats a nice day!;指针方式指针方式是用字符串常量来初始化一个字符指针:char*string_pt=Whats a nice day!;2023/8/9436.4.1 字符串处理的两种方式处理字符2024/6/17446.4.1 字符串处理的两种方式字符串处理的两种方式指针常量不能指针常量不能放在等式左边放在等式左边运行时会出运行时会出错错2023/8/9446.4.1 字符串处理的两种方式指针常量2024/6/17456.4.2 字符串操作函数字符串操作函数 实参数:字符数组名、已经初始化的字符指针,字符串常量实参数:字符数组名、已经初始化的字符指针,字符串常量目的串必须是可写的。目的串必须是可写的。2023/8/9456.4.2 字符串操作函数 实参数:字2024/6/1746 例6.14 strcpy和strncpy的比较。#includevoidmain()intn;char*array1=HappyBirthdaytoYou;chararray315;chararray225;strcpy(array2,array1);coutThestringinarray1is:array1nThestringinarray2is:array2n;/*strcpy(array3,array1);coutarray3endl;*/n=sizeof(array3);strncpy(array3,array1,n-1);/复制复制array1的的n-1个字符个字符array314=0;/添加添加0到到array3coutThestringinarray3is:array3endl;不包括提示的运行结果不包括提示的运行结果Happy Birthday to YouHappy Birthday to YouHappy Birthday 复制复制array1到到array2,没有问题复制复制array1到到array3,空间不够,有运行错误按实际数组大小,复制按实际数组大小,复制array1到到array3,没有问题2023/8/946 例6.14 strcpy和strncp2024/6/17476.5 6.5 通过指针访问数组通过指针访问数组 2023/8/9476.5 通过指针访问数组 2024/6/17486.5 通过指针访问数组通过指针访问数组指针和数组有天然的联系数组名就是地址数组名就是地址,也就是某种类型的指针虽然一维数组名和二维数组名都是地址,都可以看作是某种指针,但是指针的类型是不同的通过指针访问一维数组和二维数组的方法是不同的 2023/8/9486.5 通过指针访问数组指针和数组有天然2024/6/17496.5.1 通过指针访问一维数组通过指针访问一维数组必须声明和数组类型相同的指针,并用数组名初始化指针:int A10,*pa=A;多种方式访问数组元素多种方式访问数组元素1.数组名和下标,如A0、A4 2.指针和下标,如pa0、pa4 3.指针加偏移量的间接引用,如*(pa+4)4.数组名加偏移量的间接引用,如*(A+4)5.指针自加后的间接引用,如*pa+2023/8/9496.5.1 通过指针访问一维数组必须声明2024/6/1750 例6.15 求数组内所存放的字符串的长度 voidmain()charChArray=Thisisastring.,*ptch;inti,j,k,offset1,offset2;ptch=ChArray;/指针初始化指针初始化for(i=0;ChArrayi!=0;i+);coutThelengthofthestringis:iendl;for(j=0;ptchj!=0;j+);coutThelengthofthestringis:jendl;for(offset1=0;*(ChArray+offset1)!=0;offset1+);coutThelengthofthestringis:offset1endl;for(offset2=0;*(ptch+offset2)!=0;offset2+);coutThelengthofthestringis:offset2endl;for(k=0;*ptch+!=0;k+);coutThelengthofthestringis:kendl;运行结果都相同运行结果都相同方式1数组名下标数组名下标方式方式2 2:指针和下标:指针和下标方式方式3 3:数组名加数组名加偏移量的间接引用偏移量的间接引用方式方式4 4:指针加偏:指针加偏移量的间接引用移量的间接引用方式方式5 5:指针自加的间接引用:指针自加的间接引用2023/8/950 例6.15 求数组内所存放的字符串的长2024/6/1751 例6.16求整型数组的平均值,显示数组元素和平均值。voidmain()intintArray10=8,11,23,34,45,56,65,78,86,97,*ptint;inti,num,sum;floataverage;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 5665788697平均值是:平均值是:50.3 指针初始化指针初始化求数组元素求数组元素的数目的数目求平均值求平均值指针再次初始化指针再次初始化输出数组元输出数组元素和它们的素和它们的平均值平均值2023/8/951 例6.16求整型数组的平均值,显示数组2024/6/17526.5.2 通过指针访问二维数组通过指针访问二维数组二维数组可以看成是一维数组的一维数组 二维数组名也是地址(指针),但和一维数组名有不同的类型对一维数组A5数组名A的地址,是第一个元素A0的地址指针的类型是指向数组元素的指针A+1 A1的地址 2023/8/9526.5.2 通过指针访问二维数组二维数组2024/6/17536.5.2 通过指针访问二维数组通过指针访问二维数组对二维数组B34数组名B的地址,一维数组B0的地址指针的类型是指向一维数组的指针指针的类型是指向一维数组的指针B+1 一维数组B1的地址 2023/8/9536.5.2 通过指针访问二维数组对二维数2024/6/17546.5.2 通过指针访问二维数组通过指针访问二维数组定义指向一维数组的指针时,必须指出一维数组的大小 声明格式如下:类型名(*指针变量名)一维数组大小;例如:char(*ptchb)4,(*ptchc)2;ptchb=B;ptchc=C;2023/8/9546.5.2 通过指针访问二维数组定义指向2024/6/17556.5.2 通过指针访问二维数组通过指针访问二维数组指向一维数组的指针具有的特征:二维数组名是指向一维数组的指针,不指向数组元素 指针加1 是指向下一个一维数组的指针 指向一维数组的指针的间接引用的结果仍然是地址,即*ptchb仍然是地址,为一维数组B0第一个元素B00的地址*ptchb是数组元素的地址,*ptchb就是数组元素的值访问二维数组第i行第j列元素:*(*(指针名+i)+j)2023/8/9556.5.2 通过指针访问二维数组指向一维2024/6/1756 例6.17比较指向一维数组的指针和指向数组元素的指针 voidmain()shortB34,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 x0012FF68ptchb+1的地址是:的地址是:0 x0012FF70ptchc的地址是:的地址是:0 x0012FF5Cptchc+1的地址是:的地址是:0 x0012FF60 B B的第的第0 0行地址行地址 B B的第的第1 1行地址行地址 C C的第的第0 0行地址行地址 C C的第的第1 1行地址行地址2023/8/956 例6.17比较指向一维数组的指针和指向2024/6/1757 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=&B01)coutYesendl;不同类型的指针不同类型的指针ptshb的地址是:的地址是:0 x0012FF68*ptshb的地址是:的地址是:0 x0012FF68*ptshb+1的地址是:的地址是:0 x0012FF6AB01的地址是:的地址是:0 x0012FF6A*ptshb+1和和&B01相等吗?相等吗?Yes B B的第的第0 0行地址行地址 B B的第的第0 0行第行第0 0列列 元素的地址元素的地址 B B的第的第0 0行第行第1 1列列 元素的地址元素的地址 B B的第的第0 0行第行第1 1列列 元素的地址元素的地址2023/8/957 cout不同类型的指针n2024/6/1758 例6.18 用单循环程序,求二维数组元素的平均值。voidmain()intArray34=32,42,12,25,56,76,46,53,76,89,96,82,(*pt)4;intsum,j;floataverage;sum=0;pt=Array;j=sizeof(Array)/sizeof(*Array);for(inti=0;ij;i+)sum=sum+*(*pt+i);average=(float)sum/j;cout数据的平均值等于:averageendl;运行结果:运行结果:数 据 的 平 均 值 等 于57.0833指向一维数组指针的初始化指向一维数组指针的初始化求数组元素的数目,求数组元素的数目,*Array就是元素就是元素Array00数组求和数组求和求平均值求平均值输出平均值输出平均值2023/8/958 例6.18 用单循环程序,求二维数组元2024/6/1759一维数组:intintArray2=8,11,*ptint;sum=sum+*ptint+;二维数组:intA23=32,42,12,25,56,76,(*pt)3;sum=sum+*(*(pt+i)+j);2023/8/959一维数组:2024/6/17606.6 6.6 指针访问动态内存指针访问动态内存2023/8/9606.6 指针访问动态内存2024/6/17616.6 指针访问动态内存指针访问动态内存 动态内存:在程序执行时才可以申请、使用和释放的内存存放动态数据的区域称为“堆”,动态内存也称为堆内存堆内存 动态内存不能通过变量名来使用,只能通过指针来使用 2023/8/9616.6 指针访问动态内存 动态内存:2024/6/17626.6.1 动态内存的申请和释放动态内存的申请和释放C+中通过运算符new申请动态内存,运算符delete释放动态内存new的使用格式:new 类型名(初值)int*p;p=new int(3);申请成功:返回指定类型内存的地址申请失败:返回NULL指针2023/8/9626.6.1 动态内存的申请和释放C+中2024/6/17636.6.1 动态内存的申请和释放动态内存的申请和释放运算符delete释放动态内存delete运算符使用格式:delete 指针名;delete p;new 与delete 应该成对出现2023/8/9636.6.1 动态内存的申请和释放运算符d2024/6/17646.6.2 动态数组空间的申请和释放动态数组空间的申请和释放申请动态数组要加上数组的大小:一维:一维:new 类型名常量表达式;注意:动态申请数组空间时,不可以对数组进行初始化二维:二维:int(*pi_marray)4;pi_marray=new int34;释放动态数组空间都用相同的表达式:delete;2023/8/9646.6.2 动态数组空间的申请和释放申请2024/6/17656.6.3 内存泄漏和指针悬挂内存泄漏和指针悬挂 内存泄漏 动态申请的内存空间,没有正常释放,但也不能继续使用的情况。如:char*ch1;ch1=new char(A);char*ch2=new char;ch1=ch2;原来为ch1所申请的存放字符A的空间就不能再使用了,产生了内存泄漏 2023/8/9656.6.3 内存泄漏和指针悬挂 内存泄漏2024/6/17666.6.3 内存泄漏和指针悬挂内存泄漏和指针悬挂指针指向一个已经释放的空间,即指针悬挂 char*ch1,*ch2;ch1=new char;ch2=ch1;*ch2=B;delete ch1;指针ch2指向了一个已经释放的地址空间-指针悬挂用用delete ch2;语句来释放语句来释放ch2所指向的空间,所指向的空间,会出现运行错误会出现运行错误2023/8/9666.6.3 内存泄漏和指针悬挂指针指向一2024/6/1767 6.7 6.7 引用概念引用概念2023/8/967 6.7 引用概念2024/6/17686.7 引用概念引用概念引用(Reference)是C+中新引入的概念,是C语言中不存在的数据类型 引引用用是是变量或者其他编程实体(如对象)的别别名名因此引用不可以单独定义如图6.4(a):变量A在内存中有自己的地址,而A的引用B实际上就是变量A,只是A的另外一个名字 2023/8/9686.7 引用概念引用(Reference2024/6/17696.7.1 引用的声明和使用引用的声明和使用引用通过运算符&来定义:类型名&引用名=变量名;变量名必须已经定义变量名必须已经定义和引用的类型必须相同和引用的类型必须相同 int someInt;int&refInt=someInt;必须注意:引用必须在声明的时候就完成初始化,不可以先声明引用,然后再用另一个语句对它初始化。2023/8/9696.7.1 引用的声明和使用引用通过运算2024/6/1770改进C中函数的形参定义为指针型参数时所带来的不安全性int add(int*x,int*y)*x=*x+*y;return*x;int add(int&x,int&y)x=x+y;return x;改为改为2023/8/970改进C中函数的形参定义为指针型参数时所带2024/6/17716.7.1 引用的声明和使用引用的声明和使用引用的特点:引用不能独立存在,它只是其他变量的别名 引用必须在声明的同时初始化 引用一旦定义,引用关系就不可以更改B是A的引用,就不可能是其他变量的引用 引用的类型就是相关的变量的类型,引用的使用和变量的使用相同 2023/8/9716.7.1 引用的声明和使用引用的特点:2024/6/1772 例6.22引用的使用。观察以下程序的结果。voidmain()intintA=10;int&refA=intA;cout“引用的值和相关变量值相同:refA=refAendl;refA=5;cout“引用的变化,则相关变量也变化:intA=intAendl;cout“引 用 的 地 址 和 相 关 变 量 地 址 相 同:intA的 地 址&intAendl;cout“引用的地址和相关变量地址相同:refA的地址&refAendl;引用的值和相关变量值相同引用的值和相关变量值相同:refA=10引用的变化,则相关变量也变化:引用的变化,则相关变量也变化:intA=5引引用用的的地地址址和和相相关关变变量量地地址址相相同同:intA的的地地址址0 x0012FF7C引引用用的的地地址址和和相相关关变变量量地地址址相相同同:refA的的地地址址0 x0012FF7C2023/8/972 例6.22 引用的使用。观察以下程序的2024/6/1773 例6.23 指针的引用。voidmain()intintA=10,intB=20;int*pti=&intA;int*&refi=pti;cout“指针的引用可以访问指针所指的变量:*refi=*refiendl;cout指针变量原来的值:pti=ptiendl;refi=&intB;cout“引用的变化,则相关指针也变化:pti=ptiendl;cout指针所指的变量值也发生变化:*pti*ptiendl;指针的引用可以访问指针所指的变量指针的引用可以访问指针所指的变量:*refi=10指针变量原来的值指针变量原来的值:pti=0 x0012FF7C引引 用用 的的 变变 化化,则则 相相 关关 指指 针针 也也 变变 化化:pti=0 x0012FF78指针所指的变量值也发生变化:指针所指的变量值也发生变化:*pti202023/8/973 例6.23 指针的引用。指针的引用可2024/6/17746.7.1 引用的声明和使用引用的声明和使用如果不希望通过引用来改变相关的变量的值,可以定义常引用:const 类型名&引用名=变量名;例如:int someInt=10;const int&const_refA=someInt;const_refA就 是 常 引 用。不 可 以 通 过const_refA来改变someInt变量的值 2023/8/9746.7.1 引用的声明和使用如果不希望通2024/6/17756.7.2 通过通过引用传递函数参数引用传递函数参数引用使用最多的场合是作为函数的形式参数形式参数 引用作为函数的形参有以下特点特点:形参,实参是相同类型的变量 引用作为形参,参数传递属于地址传递地址传递 引用作为形参,在函数中并不产生实参副本是同一个实体 函数对引用的操作,也是对实参变量的操作函数调用可以改变实参数的值 2023/8/9756.7.2 通过引用传递函数参数引用使用2024/6/1776 例6.24 用引用作为形式参数,交换两个实参数。#includeusingnamespacestd;voidswap_1(int&x,int&y)/引用作为形式参数引用作为形式参数intj;j=x;x=y;y=j;voidmain()inta=12345,b=54321;cout函数调用前:a=ab=bendl;swap_1(a,b);/变量作为实参数cout函数调用后:a=ab=bendl;函 数 调 用 前:a=12345b=54321函 数 调 用 后:a=54321b=123452023/8/976 例6.24 用引用作为形式参数,交换两2024/6/1777函数返回多个值 (可以用地址,还可用引用)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/8/977函数返回多个值 (可以用地址,还可用2024/6/17786.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/8/9786.7.2 通过引用传递函数参数使用引用2024/6/17796.7.3 用用引用作为函数的返回值引用作为函数的返回值返回引用需注意注意:1.返回引用需在函数的返回值类型中加以说明 类型名&函数名(形式参数表)2.返回引用的返回语句是:return 变量名;3.返回引用实际是返回地址在使用上,或者直接使用这个地址;或者使用这个地址单元的数据 4.返回的引用可以作为左值继续操作而返回的变量值是不可以继续运算的。这是返回引用和返回变量值在使用上的主要区别。2023/8/9796.7.3 用引用作为函数的返回值返回引2024/6/1781总结指针变量的特点是可变性,即一个指针变量内的地址是可变的。所以,通过一个指针变量,就可以访问一个数组。引用的特点是不变性,一个变量的引用就只能和这个变量联系在一起。本章还介绍了函数调用的另一种方式:地址调用。具体又分为指针调用和引用调用。2023/8/981总结指针变量的特点是可变性,即一个指针变
展开阅读全文
相关资源
相关搜索

最新文档


当前位置:首页 > 办公文档 > 教学培训


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

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


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