《c指针和动态内存分配实用.pptx》由会员分享,可在线阅读,更多相关《c指针和动态内存分配实用.pptx(93页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、1Pointers to structures(指向结构体的指针)Pointers to class objects(指向类对象的指针)Pointers as function arguments(指针变量作为函数实参)Dynamic memory allocation(动态内存分配)Chapter Nine:Pointers and Dynamic Memory(指针和动态内(指针和动态内存分配)存分配)第1页/共93页29.1 Variable address(变量地址变量地址)Every variable object used in a C+program is stored in a
2、 specific place in memory.Each location in memory has a unique address,in the same way that every house in a street has a unique address.(在C+程序中使用的每个变量和对象,都存储在内存中特定的存储单元中。每个存储单元都有唯一的地址,就像街道旁的每个房子都有唯一的地址一样。)第2页/共93页3Variable address(变量地址变量地址)内存空间的访问方式通过变量名访问通过地址访问地址运算符:&例:int var;则&var 表示变量var在内存中的起始
3、地址第3页/共93页4#include#include using namespace std;void main()int var1=1;float var2=2;cout var1 has a value of var1 and is stored at&var1 endl;cout var2 has a value of var2 and is stored at&var2 endl;第4页/共93页57.1.1 地址与指针地址与指针程序中程序中:int i;float k;内存中每个字节有一个编号-地址.2000200120022005内存02003ik为其分配内存单元变量变量是对程序
4、中数据及存储空间的抽象第5页/共93页69.2 Pointer variables(指针变量指针变量)A pointer variable is a variable that holds the address of another variable.(指针变量是存放另一变量地址的变量)data_type*variable_name;int*int_ptr;float*float_ptr;其中,其中,“*”“*”表示后面声明的变量是指针类型的变表示后面声明的变量是指针类型的变量。指针变量一旦被赋值,我们就说该指针变量有量。指针变量一旦被赋值,我们就说该指针变量有了指向。了指向。“数据类型数据
5、类型”可以是任意类型,指的是指可以是任意类型,指的是指针所指向的对象类型,这说明了指针所指向的内存针所指向的对象类型,这说明了指针所指向的内存单元可以用于存放什么类型的数据,我们称之为指单元可以用于存放什么类型的数据,我们称之为指针的类型。针的类型。区分:int *p1,*p2;与 int *p1,p2;第6页/共93页7Pointer variables(指针指针声明声明例:例:int i;int*i_pointer=&i;指向整型变量的指针指向整型变量的指针使用使用例例1:i=3;例例2:*i_pointer=3;语法形式语法形式 存储类型存储类型 数据类型数据类型 *指针名初始地址;指针
6、名初始地址;例:例:int*pa=&a;20003i_pointer*i_pointeri2000注意事项 用变量地址作为初值时,该变量必须在指针初始化之前已说明过,且变量类型应与指针类型一致。可以用一个已赋初值的指针去初始化另一 个指针变量。第7页/共93页8说明:说明:在在指指针针变变量量定定义义中中,*是是一一个个说说明明符符,它它表表明明其其后后的的变变量量是是指指针针变变量量,如如在在 int*p;语语句句中中,p是是指指针针变变量量,而而不不要要认为认为“*p”是指针变量;是指针变量;指指针针变变量量定定义义时时指指定定的的数数据据类类型型不不是是指指针针变变量量本本身身的的数数据
7、据类类型型,而而是是指指针针变变量量所所指指向向的的对对象象(或或称称目目标标)的的数数据据类类型,型,指针变量指针变量只能指向只能指向定义时所规定类型的变量;定义时所规定类型的变量;定定义义后后值值不确定,而而指指针针变变量量一一旦旦被被赋赋值值,就就有有了了有有效效的的指向对象;指向对象;指指针针变变量量并并不不固固定定指指向向一一个个变变量量,可可指指向向同同类类型型的的不不同同变变量量;指指针针变变量量和和普普通通变变量量的的共共同同点点是是:它它们们都都能能存存放放数数据据,而而又又有有自自己己的的地地址址。不不同同的的是是:普普通通变变量量中中直直接接存存放放通通常常意意义下的数据
8、,而指针变量中存放的是义下的数据,而指针变量中存放的是地址地址。第8页/共93页9.2000200420062005整型变量i10变量i_pointer2001200220032000指针指针变量 变量的变量的内容内容 变量的变量的地址地址指针变量变量变量地址(指针)变量值指向地址存入指针变量指针变量和指针所指向的变量的区别:对于:int i=10,*i_pointer=&i;变量的变量的地址地址 变量的变量的内容内容指针变量是用于存放内存单元地址的变量,指针所指向的变量是指针变量中所保存的内存地址对应的变量。第9页/共93页109.3 the dereference operator*(解引
9、用运算符解引用运算符*)The dereference operator*is used to access the value of a variable,whose address is stored in a pointer.(解引用运算符*用于访问指针变量所指向的存储单元的内容。)int i=10,*i_pointer=&i;i_pointer =&i =&(*i_pointer)i =*i_pointer =*(&i)i_pointer-指针变量,它的内容是地址量指针变量,它的内容是地址量*i_pointer-指针的指针的目标变量目标变量,它的内容是数据,它的内容是数据&i_poin
10、ter-指针变量占用内存的地址指针变量占用内存的地址第10页/共93页11#include using namespace std;main()int var=1;int*ptr;ptr=&var;/ptr contains the address of var cout ptr contains ptr endl;cout “*ptr contains *ptr endl;prt contains 0012FF88*ptr contains 1 第11页/共93页12#includeusing namespace std;int main()int*p1,*p2,*p,a,b;cinab;p
11、1=&a;p2=&b;if(ab)p=p1;p1=p2;p2=p;couta=ab=bendl;coutmax=*p1min=*p2endl;return 0;第12页/共93页139.4 Using const with pointers(使用使用const修饰指针变量修饰指针变量)When defining a pointer,the pointer itself,the value it points to or both can be made constant.The position of const in the definition determines which of th
12、ese apply.(定义指针变量时,指针变量本身、指针变量所指向的数据都可以声明为常量。变量定义中的const的位置决定了谁被声明为常量。)第13页/共93页14 int i=3,j=4;(a)const int*p=&i;/*p is a constant but p is not.*p=5;/Illegal:cannot change i using p.i=5;/Legal:i is not a constant.p=&j;/Legal:p now point to j.*p=4(b)int const*p=&i;/*p is a constant;p is not.(c)int*co
13、nst p=&i;/p is a constant;*p is not.*p=5;/Legal:*p can be changed.i=5 p=&j;/Illegal:p is a constant.(d)const int*const p=&i;/both p and*p are constants.*p=5;/Illegal:*p is a constant.p=&j;/Illegal:p is a constant.第14页/共93页15指针与常量指针与常量 指向常变量的指指向常变量的指针针不能通过指针来改变所指对象的值,但指针本身可以改变,可以指向另外的对象。例:const int n
14、2=5;const int*pn=&n2;*pn=6;/错误例:const char*name1=“John”;char s=“abc”;name1=s;对 *name1=1;错第15页/共93页16定义指向常变量的指针变量形式:const 类型名*指针变量名如:const char*ptr;(1)如果一个变量已经被声明为常变量,只能用指向常变量的指针变量指向它,而不能用一般的指针变量去指向它。如:const char c=“boy”;const char*pp=c;char*p2=c;/不合语法。第16页/共93页17(2)指向常变量的指针变量除了可以指向常变量外,还可以指向未被声明为 co
15、nst型的变量,此时不能通过指针变量改变该变量的值。char c1=a;const char*p;p=&c1;*p=b;/错误c1=b;第17页/共93页18指针与常量指针与常量 常量指常量指针针若声明指针常量,则指针本身的值不能被改变。但是它指向的整型变量是可以改变的。例:int n1=3;const int n2=5;int *const pn=&n1;pn=&n2;/错误*pn=6;/正确例:char*const name1=“John”;name1=“abc”;错第18页/共93页19例例 指向常量的指针做形参指向常量的指针做形参#includeconst int N=6;void p
16、rint(const int*p,int n);void main()int arrayN;for(int i=0;iarrayi;print(array,N);第19页/共93页20void print(const int*p,int n)cout*p;for(int i=1;in;i+)cout.*(p+i);coutendl;1 2 3 4 5 61.2.3.4.5.6 第20页/共93页219.5 Pointers and one-dimensional arrays Ponters and arrays are directly related to one another.In c
17、+,the name of an array is equivalent to the address of the first element of the array.The name of an array,therefore,is a pointer to the first element of the array.(指针和数组是相互联系的。在C+中,数组名代表数组的首地址。因此,数组名即为指向数组第一个元素的指针。)int a5;a&a0 a+1&a1 As the name of an array is a pointer to the first element of the
18、array,the dereference operator*can be used to access the elements of the array.第21页/共93页22Pointers and one-dimensional arrays指向数组元素的指针int a10;int*p;p=&a0;/把a0元素的地址赋给指针变量p,也就是使指针变量p指向a数组的第0号元素。它等价于p=a;/它表示把数组首元素的地址赋给p。int*p=&a0;它等价于int*p;p=&a0;也可以定义为 int*p=a;*p=1;第22页/共93页23Pointers and one-dimension
19、al arrays如果指针变量p已经指向数组中得一个元素,则P+1指向同一数组中得下一个元素。int array 10=1,2,3,4,5,6,7,8,9,10,*p;当p=array时下面的等价关系成立:p=array=&array0/表示数组元素的首地址p+i=array+i=&arrayi;/表示第i个数组元素的地址*(p+i)=*(array+i)=arrayi/表示第i个数组元素指向数组的的指针变量也可以带下标,所以p+i和pi是一样的、第23页/共93页24引用数组元素引用数组元素可以有三种方法:(1)下标法:数组名下标 a1(2)指针变量法:*指针变量 *(P+i)(3)首地址法
20、:*(首地址+位移量)*(array+i)第24页/共93页25如果先使指针变量p指向数组a的首地址(p=a)则:(1)p+使p指向下一个元素,即a1,用*p可以得到下一个元素a1的值,(2)*p+先得到p指向的变量的值,然后再使P得值加1,使p指向下一个元素,for(p=a;pa+10;)cout*p+;(3)*(p+)和*(+P)不同,后者是先使P加1,在求*P的值。(4)(*p)+表示P所指向的元素值加1.第25页/共93页26#include using namespace std;main()int a5=10,13,15,11,6 ;for(int i=0;i 5;i+)cout
21、Element i is *(a+i)endl;Element 0 is 10 Element 1 is 13 Element 2 is 15 Element 3 is 11 Element 4 is 6 第26页/共93页27 Although the name of an array is a pointer to the first element of the array,you cannot change its value;this is because it is a constant pointer.(虽然数组名是指向数组第一个元素的指针,但是由于它是一个常量指针,因此它的值是
22、不能改变的。)int a10;float numbers100;a+;number+=2;Pointers and one-dimensional arrays第27页/共93页28 You can assign the name of an array to a pointer variable of the same type.int a5;int*p;p=a;/valid:assiqnment of a constant to a variable a+;/Invalia:the value of a costant cannot change.p+;/Valid:p is a vari
23、able.p now points to element 1 of the array a.p-;/Valid:point to element 1 of the array a.p+=10;/Valid.But p is outside the range of the array a./so*p is underfined.A common error.p=a-1;/Valid,but p is outside the ranger of the array.Pointers and one-dimensional arrays第28页/共93页29 A constant may be a
24、dded to or subtancted from the value of a pointer.allowing access to different memory to locations.Hower,not all arithmeic operations are permissible on poniters.For example,the multiplication of two pointers is illegal,because the result would not be a valid memory address.(通过将指针变量加上或减去一个常量,可以使它指向不
25、同的存储单元。但是,并非所有的算术运算符都可以应用于指针。例如,两个指针相乘是非法的,因为相乘的结果可能不是一个有效的内存地址。)Pointers and one-dimensional arrays第29页/共93页30分别用三种方式访问数组中的所有元素分别用三种方式访问数组中的所有元素void main()int i,array10=1,2,3,4,5,6,7,8,9,10,*p;coutNO1:;for(i=0;i10;i+)coutarrayi=arrayi;coutnNO2:n;for(i=0;i10;i+)cout*(array+“i)=*(array+i);coutnNO3(1)
26、n;for(p=array,i=0;i10;i+)cout*(p+“i)=*(p+i);coutnNOs(2)n;for(p=array;parray+10;p+)cout*p+=“*p;coutn;第30页/共93页31A two-dimensional array is stored as an array of arrays.This means that a is a one-dimensional array whose elements are themselves a one-dimensional arrays of integers.As with one-dimensona
27、l array,the name of a two dimensional array is pointer to the first element of the array.Therefore a is equivalent to&a 0,a 0 is itself an array of two intergers,which means that a 0 is equivalent to&a00.Pointers and multi-dimensional arrays第31页/共93页32a+2a0a00a03a10a13a20a23a1a2aa+1a0+0a0+3a1+3a2+3i
28、nt a34;a13 *(a1+3)*(*(a+1)+3)第32页/共93页33#includeusing namespace std;int main()int a34=1,3,5,7,9,11,13,15,17,19,21,23;int*p;for(p=a0;pa0+12;p+)cout*p;cout成员名成员名例:struct stu date,*pstu=&date;则:pstu-num 等价于 (*pstu).num第35页/共93页36指向结构体变量的指针指向结构体变量的指针#includeusing namespace std;int main()struct student i
29、nt num;string name;char sex;float score;student stu;student*p=&stu;stu.num=10301;stu.name=WangFun;stu.sex=f;stu.score=89.5;coutstu.num stu.name stu.sex stu.scoreendl;cout(*p).num(*p).name(*p).score(*p).sex成员名 -指向运算符P-n得到P指向的结构体变量中的成员n的值。p-n+得到p指向的结构体变量中成员n的值,用完改值后使它加1.+p-n得到p指向的结构体变量中的成员n的值,并使之加1,然后
30、再使用它。第37页/共93页38用指向结构体变量的指针作实参#include#includeusing namespace std;struct studentint num;string name;float score3;stu=12345,lifung,67.5,89,78.5;int main()void print(student*);student*pt=&stu;print(pt);return 0;void print(student*p)coutnum“name“score0“score1“score2成员名第40页/共93页41Class Time public:int h
31、our;int minute;int sex;void get_time();Void Time:get_time()couthour“:”minute“:”sexhour p1所指向的对象中的hour成员,t1.hour(*p1).get_time 调用p1所指向的对象中的get_time 函数,t1.get_timeP1-get_time 调用p1所指向的对象中的get_time 函数,t1.get_time第42页/共93页43例例 对象指针应用举例对象指针应用举例void main()Point A(5,10);Point*ptr;ptr=&A;int x;x=ptr-GetX();c
32、outxendl;第43页/共93页44Example#include#include#include bank_ac.h#include bank_ac.cppusing namespace std;main()bank_account ac;/ac is a bank_account object.bank_account*ac_ptr;/ac_ptr is a pointer to a bank_account.ac_ptr=∾/ac_ptr contains the address of the object ac.ac_ptr-deposit(100);ac_ptr-displ
33、ay_balance();ac-ptr -deposit(100);(*ac_ptr).deopsit(100);第44页/共93页45 9.9 Pointers as funtion arguments Like any data type,pointers can be used as function arguments.第45页/共93页46#include using namespace std;void swap_vals(float*val1,float*val2);main()float num1,num2;cout num1;cin num2;if(num1 num2)swa
34、p_vals(&num1,&num2);cout The numbers in order are num1 and num2 endl;void swap_vals(float*ptr1,float*ptr2)float temp=*ptr1;*ptr1=*ptr2;*ptr2=temp;Please enter two number:12.1 6.4The numbers in order are 6.4 and 12.1第46页/共93页479.10 Dynamic memory allocationC+has the ability to allocate memory while a
35、 program is executing.This is done by using the memory allocation operator new.第47页/共93页48 Dynamic memory allocation动态申请内存操作符 newnew 类型名T(初值列表)功能:在程序执行期间,申请用于存放T类型对象的内存空间,并依初值列表赋以初值。结果值:成功:T类型的指针,指向新分配的内存。失败:0(NULL)第48页/共93页49new运算符的例子;new int;/开辟一个存放整数的存储空间,返回一个指向该存储空间的地址(即指针)new int(100);/开辟一个存放整数
36、的存储空间,并指定该整数的初值为100,返回一个指向该存储空间的地址(即指针),new char10;/开辟一个存放字符数组的(包含10个元素)空间,返回首元素的地址。new int54;/开辟一个存放二维整型数组(大小为5*4)的空间,返回首元素的地址。float*p=new float(3.14159);/开辟一个存放单精度数的空间,并指定该实数的初值是3.14159,将返回的该空间的地址赋给指针变量p。第49页/共93页50释放内存操作符释放内存操作符deletedelete 运算符使用的一般格式为:delete 指针P功能:释放指针P所指向的内存。P必须是new操作的返回值。delet
37、e p;new char10;如果把 new返回的指针付给指针变量pt,则用 delete pt;/在指针变量前面加一对方括号,表示是对数组空间的操作。第50页/共93页51#include#includeusing namespace std;struct studentchar*name;int num;char sex;int main()student*p;p=new student;p-name=wang Fun;p-num=10123;p-sex=m;coutnameendlnumendlsexendl;delete p;return 0;第51页/共93页52例例 动态存储分配举
38、例动态存储分配举例#include struct date int month;int day;int year;第52页/共93页53void main()int index,*point1,*point2;point1=&index;*point1=77;point2=new int;*point2=173;cout The values are index *point1 *point2 n;delete point2;point1=new int;point2=point1;*point1=999;cout The values are index *point1 *point2 mo
39、nth=10;date_point-day=18;date_point-year=1938;cout month /day /year n;delete date_point;/释放结构体第55页/共93页56 char*c_point;c_point=new char37;/动态分配数组 delete c_point;/释放数组 c_point=new charsizeof(date)+133;/动态分配数组 delete c_point;/释放数组 return 0;运行结果:The values are 77 77 173The values are 77 999 99910/18/19
40、38第56页/共93页57对象的动态建立和释放对象的动态建立和释放如果已经定义了一个box类,可以用下面的方法动态的建立一个对象:new box;定义一个指向本类的对象的指针变量来存放地址box*pt;pt=new box;第57页/共93页58在程序中就可以通过pt访问这个新建的对象,coutheighr;coutvolume();c+还允许在执行new时,对新建的对象进行初始化。可以使用delete运算符对新建的对象所占有的空间进行套释放。delete pt;在执行运算符时,自动调用析构函数。第58页/共93页59例例 动态创建对象举例动态创建对象举例#includeclass Point
41、 public:Point()X=Y=0;coutDefault Constructor called.n;Point(int xx,int yy)X=xx;Y=yy;cout Constructor called.n;Point()coutDestructor called.n;int GetX()return X;int GetY()return Y;void Move(int x,int y)X=x;Y=y;private:int X,Y;第59页/共93页60void main()coutStep One:endl;Point*Ptr1=new Point;delete Ptr1;co
42、utStep Two:endl;Ptr1=new Point(1,2);delete Ptr1;运行结果:Step One:Default Constructor called.Destructor called.Step Two:Constructor called.Destructor called.第60页/共93页61例例 动态创建对象数组举例动态创建对象数组举例#includeclass Point /类的声明同例6-15,略;void main()Point*Ptr=new Point2;/创建对象数组 Ptr0.Move(5,10);/通过指针访问数组元素的成员 Ptr1.Mov
43、e(15,20);/通过指针访问数组元素的成员 coutDeleting.endl;delete Ptr;/删除整个对象数组运行结果:Default Constructor called.Default Constructor called.Deleting.Destructor called.Destructor called.第61页/共93页62访问对象的数据成员访问对象的数据成员#include using namespace std;class Humanpublic:int get()constreturn i;void set(int x)i=x;private:int i;in
44、t main()Human*p=new Human;p-set(1);coutget()endl;delete p;return 0;运行结果:1第62页/共93页63在构造函数中开辟空间在构造函数中开辟空间#include using namespace std;class Humanpublic:int get()constreturn*i;void set(int x)*i=x;Human();Human();private:int*i;Human:Human()cout构造函数执行中.n;i=new int(999);int main()Human*p=new Human;coutge
45、t()set(1);coutget()endl;delete p;return 0;Human:Human()cout析构函数执行中.n;delete i;构造函数执行中9991析构函数执行中第63页/共93页649.10.1 Allocating memory dynamically for an arrayThe new memory allocation operator can be used to allocate a contiguous block of memory for an array of any type,whether the data type is built-
46、in or is a user-defined structure of class.pointer=new data_typesize;For example:/Allocate memory for 10 integers.int_ptr=new int10;/Allocate memory for 5 bank_account objects.ac_ptr=new bank_account5;When allocating memory for an array of class objects,there must be a default constructor for the cl
47、ass so that the elements of the array get initialised.(当为一个类对象数组动态分配内存时,这个类必须有自己的默认构造函数来初始化类对象数组元素。)第64页/共93页65/dynamic memory allocation for an array of integers.#includeusing namespace std;main()int*int_array;int no_els,i;cout no_els;int_array=new intno_els;for(i=0;i no_els;i+)cout “Enter element”
48、i int_arrayi;for(i=0;i no_els;i+)cout“Element”i“is“*(int_array+i)endl;delete int_array;Enter the number of elements 2Enter element 0:57Enter element 1:69Element 0 is 57Element 1 is 69第65页/共93页66The elements of the newly allocated array can be accessed using either a pointer or an index.(可以使用指针或下标方式访
49、问新分配内存的数组元素。)int_array1*(int_array+1)The allocated memory is freed using the delete operator.It is important to remember to include the square brackets when freeing memory for a previously allocated array.Without the square brackets,only the first element of the array will be deleted.(可以使用delete运算符释
50、放已分配的内存。当为一个数组释放先前动态分配的内存时,必须用方括号。如果不加释放的仅是数组的第一个元素的内存。)第66页/共93页679.10.2 Initialisation with newuWhen allocating memory for an array of class objects,the default constructor for the class initialises the elements of the array.(当为一个类对象的数组动态分配内存时,会自动调用类的默认构造函数对数组元素进行初始化。)Ac_ptr=new bank_account5;resu