第七章-动态内存分配--C++程序设计-计算机等级考试教学课件.ppt

上传人:可****阿 文档编号:82376707 上传时间:2023-03-25 格式:PPT 页数:33 大小:2.57MB
返回 下载 相关 举报
第七章-动态内存分配--C++程序设计-计算机等级考试教学课件.ppt_第1页
第1页 / 共33页
第七章-动态内存分配--C++程序设计-计算机等级考试教学课件.ppt_第2页
第2页 / 共33页
点击查看更多>>
资源描述

《第七章-动态内存分配--C++程序设计-计算机等级考试教学课件.ppt》由会员分享,可在线阅读,更多相关《第七章-动态内存分配--C++程序设计-计算机等级考试教学课件.ppt(33页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、第七章第七章 动态内存分配动态内存分配主讲人:主讲人:XXXXXX电子邮件:电子邮件:联系电话:联系电话:2023/2/211动态内存分配动态内存分配本章首先介绍程序运行时本章首先介绍程序运行时动态内存分配动态内存分配(dynamic dynamic memory allocationmemory allocation)的概念与方法;再进一步讨论复)的概念与方法;再进一步讨论复制构造函数制构造函数.7.1.17.1.1自由存储区自由存储区内存内存的分配与释放的分配与释放 7.1.27.1.2自由存储区自由存储区对象对象与构造函数与构造函数 7.1.3 7.1.3 浅复制与深复制浅复制与深复制

2、2023/2/212计算机基础教研室计算机基础教研室自由存储区内存分配自由存储区内存分配 静态存储分配:静态存储分配:无论全局或局部变量无论全局或局部变量(对象对象),编译器在,编译器在编译时编译时都可以根都可以根据该变量据该变量(对象对象)的类型知道所需内存空间的大小,从而的类型知道所需内存空间的大小,从而系统在适当的时候为它们分配确定的存储空间。尤其是系统在适当的时候为它们分配确定的存储空间。尤其是数组。数组。动态存储分配:动态存储分配:有些操作对象只有在程序有些操作对象只有在程序运行时运行时才能确定,这样编译器才能确定,这样编译器在编译时就无法为他们预定存储空间,只能在程序运行在编译时就

3、无法为他们预定存储空间,只能在程序运行时,系统根据运行时的要求进行内存分配,称为动态存时,系统根据运行时的要求进行内存分配,称为动态存储分配。动态分配都在储分配。动态分配都在自由存储区自由存储区中进行。中进行。2023/2/213计算机基础教研室计算机基础教研室自由存储区自由存储区内存的分配与释放内存的分配与释放当当程程序序运运行行到到需需要要动动态态分分配配变变量量或或对对象象时时,必必须须向向系系统统申申请请取取得得自自由由存存储储区区中中的的一一块块所所需需大大小小的的存存贮贮空空间间,用用于于存存贮贮该该变变量量或或对对象象。当当不不再再使使用用该该变变量量或或对对象象时时,也也就就是

4、是它它的的生生命命结结束束时时,要要显显式式释释放放它它所所占占用用的的存存贮贮空空间间,这这样样系系统统就就能能进进行行再再次次分配,做到重复使用有限的资源。分配,做到重复使用有限的资源。动态分配与释放:动态分配与释放:2023/2/214计算机基础教研室计算机基础教研室一般定义变量和对象时要用标识符命名,称一般定义变量和对象时要用标识符命名,称命名命名对象对象,而动态的称,而动态的称无名对象无名对象(请注意与栈区中的请注意与栈区中的临时对象的区别,两者完全不同:生命期不同,临时对象的区别,两者完全不同:生命期不同,操作方法不同,临时变量对程序员是透明的操作方法不同,临时变量对程序员是透明的

5、)。自由存储区自由存储区是不会自动在分配时做初始化的(包是不会自动在分配时做初始化的(包括清零),所以必须用初始化式括清零),所以必须用初始化式(initializer)(initializer)来显式初始化。来显式初始化。无名对象:无名对象:自由存储区自由存储区内存的分配与释放内存的分配与释放2023/2/216计算机基础教研室计算机基础教研室newnew表达式的操作:表达式的操作:从自由存储区分配对象,然后用括号中的值初始化从自由存储区分配对象,然后用括号中的值初始化该对象该对象。分配对象时,分配对象时,new表达式调用库操作符表达式调用库操作符new():int*pi=new int(0

6、);pi现在所指向的变量的存储空间是由库操作符现在所指向的变量的存储空间是由库操作符new()分配的,位于程序的自由存储区中,并且该对象分配的,位于程序的自由存储区中,并且该对象未命名。未命名。自由存储区自由存储区内存的分配与释放内存的分配与释放2023/2/217计算机基础教研室计算机基础教研室自由存储区自由存储区i演示:演示:用初始化式用初始化式(initializer)(initializer)来显式初始化来显式初始化 int*pi=new int(0);当当pipi生命周期结束时,生命周期结束时,必须释放必须释放pipi所指向的目标:所指向的目标:delete pi;注意这时释放了注意

7、这时释放了pipi所指的目标的内存空间,也就是撤销了该所指的目标的内存空间,也就是撤销了该目标,称动态内存释放(目标,称动态内存释放(dynamic memory deallocationdynamic memory deallocation),),但但指针指针pipi本身并没有撤销本身并没有撤销,该指针所占内存空间并未释放。,该指针所占内存空间并未释放。自由存储区自由存储区内存的分配与释放内存的分配与释放2023/2/218计算机基础教研室计算机基础教研室动态分配数组与动态分配数组与标准字符串类标准字符串类:标准字符串类标准字符串类string就是采用动态建立数组的方式解决就是采用动态建立数

8、组的方式解决数组溢出的问题的,例数组溢出的问题的,例7.1所做的动态内存分配与释放,所做的动态内存分配与释放,在在string类对象中都是自动完成的,在程序中不需要也不类对象中都是自动完成的,在程序中不需要也不允许再显式地为允许再显式地为string进行动态内存的分配与释放。进行动态内存的分配与释放。【例例7.1】动态数组的建立与撤销动态数组的建立与撤销自由存储区自由存储区内存的分配与释放内存的分配与释放2023/2/2110计算机基础教研室计算机基础教研室【例例7.1】动态数组的建立与撤销动态数组的建立与撤销#include#include using namespace std;int m

9、ain()int n;char*pc;cout请输入动态数组的元素个数请输入动态数组的元素个数n;/在运行时确定,可输入在运行时确定,可输入25pc=new charn;strcpy(pc,自由存储区内存的动态分配自由存储区内存的动态分配);coutpcendl;delete pc;/释放释放pc所指向的所指向的n个字符的内存空间个字符的内存空间return 0;2023/2/2111计算机基础教研室计算机基础教研室1.动态分配失败动态分配失败。返回一个空指针(。返回一个空指针(NULL),表示发生了异),表示发生了异常,堆资源不足,分配失败。常,堆资源不足,分配失败。2.指针删除与自由存储区

10、空间释放指针删除与自由存储区空间释放。删除一个指针。删除一个指针p(delete p;)实际意思是删除了)实际意思是删除了p所指的目标(变量或对象等),释所指的目标(变量或对象等),释放了它所占的自由存储区空间,而不是删除本身,释放自放了它所占的自由存储区空间,而不是删除本身,释放自由存储区空间后,成了空悬指针。空悬指针是程序错误的由存储区空间后,成了空悬指针。空悬指针是程序错误的一个根源)。建议这时将置空(一个根源)。建议这时将置空(NULL)。)。自由存储区自由存储区内存的分配与释放内存的分配与释放指针使用的要点:指针使用的要点:2023/2/2113计算机基础教研室计算机基础教研室5内存

11、泄漏(内存泄漏(memory leak)和重复释放)和重复释放。new与与delete 是配对使用的,是配对使用的,delete只能释放只能释放自由存储区自由存储区空间。空间。如果如果new返回的指针值丢失,则所分配的返回的指针值丢失,则所分配的自由存储区自由存储区空间空间无法回收,称内存泄漏,同一空间重复释放也是危险的,无法回收,称内存泄漏,同一空间重复释放也是危险的,因为因为该空间可能已另分配该空间可能已另分配,所以必须妥善保存,所以必须妥善保存new返回的返回的指针,以保证不发生内存泄漏,也必须保证不会重复释放指针,以保证不发生内存泄漏,也必须保证不会重复释放自由存储区自由存储区内存空间

12、。内存空间。自由存储区自由存储区内存的分配与释放内存的分配与释放指针使用的要点:指针使用的要点:2023/2/2115计算机基础教研室计算机基础教研室自由存储区自由存储区对象与构造函数对象与构造函数 类对象动态建立与删除过程:类对象动态建立与删除过程:通过通过new建立的对象要调用构造函数,通过建立的对象要调用构造函数,通过delete删除对删除对象也要调用析构函数。象也要调用析构函数。CGoods*pc;pc=new CGoods;/分配自由存储区空间,并构造一个无名的分配自由存储区空间,并构造一个无名的CGoods对象;对象;.delete pc;/先析构,然后将内存空间返回给自由存储区;

13、先析构,然后将内存空间返回给自由存储区;自由存储区自由存储区对象的生命期并不依赖于建立它的作用域,所以对象的生命期并不依赖于建立它的作用域,所以除非程序结束,除非程序结束,自由存储区自由存储区对象(无名对象)的生命期不会对象(无名对象)的生命期不会到期,并且需要显式地用到期,并且需要显式地用delete语句析构该类对象,上例执语句析构该类对象,上例执行行delete语句时,语句时,C+自动调用商品类的析构函数。自动调用商品类的析构函数。2023/2/2116计算机基础教研室计算机基础教研室类说明:类说明:class CGoods string Name;int Amount;float Pri

14、ce;float Total_value;public:CGoods()cout调用默认构造函数调用默认构造函数endl;CGoods(string name,int amount,float price)cout调用三参数构造函数调用三参数构造函数endl;Name=name;Amount=amount;Price=price;Total_value=price*amount;CGoods()cout调用析构函数调用析构函数endl;【例例7.37.3】演示自由存储区对象分配和释放。演示自由存储区对象分配和释放。2023/2/2118计算机基础教研室计算机基础教研室使用:使用:int mai

15、n()int n;CGoods*pc,*pc1,*pc2;pc=new CGoods(“夏利夏利2000”,10,118000);/调用三参数构造函数调用三参数构造函数 pc1=new CGoods();/调用默认构造函数调用默认构造函数 cout输入商品类数组元素数输入商品类数组元素数n;pc2=new CGoodsn;/动态建立数组,不能初始化,调用动态建立数组,不能初始化,调用n次默认构造函数次默认构造函数 delete pc;delete pc1;delete pc2;return 0;2023/2/2119计算机基础教研室计算机基础教研室例例6-16 6-16 动态创建对象举例动态创

16、建对象举例#include#includeusing namespace std;using namespace std;class Pointclass Point public:public:Point()Point()X=Y=0;coutDefault Constructor called.n;X=Y=0;coutDefault Constructor called.n;Point(int xx,int yy)Point(int xx,int yy)X=xx;Y=yy;cout Constructor called.n;X=xx;Y=yy;cout Constructor called.

17、n;Point()coutDestructor called.n;Point()coutDestructor called.n;int GetX()return X;int GetX()return X;int GetY()return Y;int GetY()return Y;void Move(int x,int y)void Move(int x,int y)X=x;Y=y;X=x;Y=y;private:private:int X,Y;int X,Y;2023/2/2120计算机基础教研室计算机基础教研室int main()coutStep One:endl;Point*Ptr1=ne

18、w Point;delete Ptr1;coutStep Two:endl;Ptr1=new Point(1,2);delete Ptr1;return 0;运行结果:运行结果:Step One:Step One:Default Constructor Default Constructor called.called.Destructor called.Destructor called.Step Two:Step Two:Constructor called.Constructor called.Destructor called.Destructor called.21例例6-16 6-

19、16 动态创建对象举例动态创建对象举例2023/2/2121计算机基础教研室计算机基础教研室浅复制(浅拷贝)浅复制(浅拷贝)实现对象间数据元素的一一对应复制。实现对象间数据元素的一一对应复制。深复制(深拷贝)深复制(深拷贝)当被复制的对象数据成员是指针类型时,不是复制当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指针所指的对象进行复制。该指针成员本身,而是将指针所指的对象进行复制。浅复制与深复制浅复制与深复制 2023/2/2122计算机基础教研室计算机基础教研室 当当浅复制浅复制析构时,如用默认的析构函析构时,如用默认的析构函数,则动态分配的数,则动态分配的自由存储区自由

20、存储区对象不能对象不能回收。如果在析构函数中有回收。如果在析构函数中有“delete p;”语句,则如果先析构函数语句,则如果先析构函数obj1时,时,自由存储区自由存储区对象已经释放,以后再析构对象已经释放,以后再析构obj2时出现了二次释放的问题。时出现了二次释放的问题。自自 由由存存 储储区区 对对象象PP自自 由由存存 储储区区 对对象象 图图7.2 深复制深复制 深复制:深复制:重新定义复制的构造函数,重新定义复制的构造函数,给每个对象独立分配一个给每个对象独立分配一个自由存储区自由存储区对象,称对象,称深复制深复制。这时先复制对象主这时先复制对象主体,再为体,再为obj2分配一个分

21、配一个自由存储区自由存储区对对象,最后用象,最后用obj1的的自由存储区自由存储区对象复对象复制制obj2的的自由存储区自由存储区对象。对象。obj1obj2浅复制与深复制浅复制与深复制 2023/2/2124计算机基础教研室计算机基础教研室浅复制与深复制浅复制与深复制【例例7.4】定义复制构造函数定义复制构造函数(copy structor)和复制赋值操)和复制赋值操作符(作符(copy Assignment Operator)实现深复制。)实现深复制。学生类定义:学生类定义:class student char*pName;/为了演示深复制,不用为了演示深复制,不用string类类publ

22、ic:student();/默认构造函数默认构造函数 student(char*pname);/带参数带参数构造函数构造函数 student(student&s);/复制构造函数复制构造函数 student();/析构函数析构函数 student&operator=(student&s);/复制赋值操作符复制赋值操作符检验检验主函数主函数和和运行结果运行结果2023/2/2125计算机基础教研室计算机基础教研室例例7.4 7.4 实现深复制实现深复制默认构造函数:默认构造函数:student:student()coutConstructor;pName=NULL;cout默认默认“endl;带

23、参数带参数构造函数:构造函数:student:student(char*pname)coutConstructor;if(pName=new charstrlen(pname)+1)strcpy(pName,pname);coutpNameendl;2023/2/2126计算机基础教研室计算机基础教研室例例7.4 7.4 实现深复制实现深复制复制赋值操作符:复制赋值操作符:student&student:operator=(student&s)coutCopy Assign operator;delete pName;/如原来已分配,应先撤销,再重分配如原来已分配,应先撤销,再重分配 if(s

24、.pName)/否则会发生内存泄漏否则会发生内存泄漏 if(pName=new charstrlen(s.pName)+1)strcpy(pName,s.pName);else pName=NULL;coutpNameendl;return*this;2023/2/2128计算机基础教研室计算机基础教研室例例7.4 7.4 实现深复制实现深复制int main(void)student s1(范英明范英明),s2(沈俊沈俊),s3;student s4=s1;s3=s2;return 0;2023/2/2129计算机基础教研室计算机基础教研室思考:思考:深入地考虑深入地考虑【例例7.47.4】

25、,如果数据域还有很多其他数据,如果数据域还有很多其他数据,甚至有好几个是动态建立的甚至有好几个是动态建立的C C字符串,深复制是不是太复杂字符串,深复制是不是太复杂了?如果使用了?如果使用C+C+标准字符串标准字符串stringstring作为成员对象(聚合)作为成员对象(聚合)是否就不需要考虑深复制了?是否就不需要考虑深复制了?的确是这样的,准确地说,的确是这样的,准确地说,string类的内部包含动态建立字类的内部包含动态建立字符数组的操作,其复制构造函数是深复制。如果在符数组的操作,其复制构造函数是深复制。如果在student类中使用类中使用string类而不是类而不是C字符串,就不要再

26、考虑深复制问字符串,就不要再考虑深复制问题了。也就是说,题了。也就是说,动态内存分配和深复制应该放在一个适当动态内存分配和深复制应该放在一个适当的层面上的层面上,一个更单纯的类定义中,如,一个更单纯的类定义中,如string类。在使用中,类。在使用中,把它作为一个成员对象,就像使用把它作为一个成员对象,就像使用string类对象那样。类对象那样。浅复制与深复制浅复制与深复制2023/2/2131计算机基础教研室计算机基础教研室探讨:探讨:最后进一步讨论类的封装。封装的更高境界是最后进一步讨论类的封装。封装的更高境界是在该类对象中一切都是完备的、自给自足的,不仅在该类对象中一切都是完备的、自给自足的,不仅有数据和对数据的操作,还包括资源的动态安排和有数据和对数据的操作,还包括资源的动态安排和释放。在需要时可以无条件地安全使用。标准释放。在需要时可以无条件地安全使用。标准string类模板就是典型的例子。这样的类对象,作类模板就是典型的例子。这样的类对象,作为另一个类的成员对象使用时,就不会出任何问题。为另一个类的成员对象使用时,就不会出任何问题。这表明这表明聚合实现了完善的封装聚合实现了完善的封装。浅复制与深复制浅复制与深复制2023/2/2132计算机基础教研室计算机基础教研室QUESTION?谢谢 谢谢2023/2/2133

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 生活常识

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

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁