欢迎来到三一办公! | 帮助中心 三一办公31ppt.com(应用文档模板下载平台)
三一办公
全部分类
  • 办公文档>
  • PPT模板>
  • 建筑/施工/环境>
  • 毕业设计>
  • 工程图纸>
  • 教育教学>
  • 素材源码>
  • 生活休闲>
  • 临时分类>
  • ImageVerifierCode 换一换
    首页 三一办公 > 资源分类 > PPT文档下载  

    re动态内存分配.ppt

    • 资源ID:6517499       资源大小:319.99KB        全文页数:43页
    • 资源格式: PPT        下载积分:15金币
    快捷下载 游客一键下载
    会员登录下载
    三方登录下载: 微信开放平台登录 QQ登录  
    下载资源需要15金币
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    re动态内存分配.ppt

    动态内存分配,程序运行时动态内存分配(dynamic memory allocation)先复习概念与方法、堆对象与构造函数 然后进一步讨论拷贝构造函数.,堆内存分配,通常编译器在编译时都可以根据变量(或对象)的类型知道所需内存空间的大小,从而在适当的时候为他们分配确定的存储空间。这种内存分配称为静态存储分配。有些操作对象只有在程序运行时才能确定,系统根据运行时的要求进行内存分配,这种方法称为动态存储分配。,1.堆内存的分配与释放,根据申请动态分配,用后显式释放所空间,使系统能做到重复使用有限的资源。,格式如下:指针变量名=new 类型名(初始化式);delete 指针变量名;new运算符返回的是一个指向所分配类型变量(对象)的指针。对所创建的变量或对象,都是通过该指针来间接操作的,而动态创建的对象本身没有名字。,堆区不会自动在分配时做初始化(包括清零),所以必须用初始化操作(initializer)来显式初始化。,从堆区分配对象时,new表达式调用库操作符new()。例如:int*pi=new int(0);/对象未命名它与下列代码序列大体等价:int what=0;int*pi=,0,pi,堆,i,演示:用初始化式(initializer)来显式初始化 int*pi=new int(0);当pi生命周期结束时,必须释放pi所指向的目标:delete pi;注意这时释放了pi所指的目标的内存空间,也就是撤销了该目标,称动态内存释放(dynamic memory deallocation),但指针pi本身并没有撤销,该指针所占内存空间并未释放。,对于数组进行动态分配的格式为:指针变量名=new 类型名下标表达式;释放:Delete 指向该数组的指针变量名;,如果delete语句中少了方括号,因编译器认为该指针是指向数组第一个元素的指针,会产生回收不彻底的问题(只回收了第一个元素所占空间),加了方括号后就转化为指向数组的指针,回收整个数组。,#include void main()int n;char*pc;coutn;/在运行时确定,可输入17pc=new charn;strcpy(pc,堆内存的动态分配);coutpcendl;delete pc;/释放pc所指向的n个字符的内存空间return;,【例1】动态一维数组的建立与撤销,动态分配数组有三个特点:,1.变量n在编译时没有确定的值,而是在运行中输入,按运行时所需分配堆空间,这一点是动态分配的优点,可克服数组“大开小用”的弊端。delete pc是将n个字符的空间释放,而用delete pc则只释放了一个字符的空间;,2.如果有一个char*pc1,令pc1=p,同样可用delete pc1来释放该空间。尽管C+不对数组作边界检查,但在堆空间分配时,对数组分配空间大小是纪录在案的。,3.没有初始化式,不可对数组初始化。,两种方法:动态创建二维数组,double*data,*score;/方法1:score=new doublemn;/方法2:data=new double*m;for(int j=0;jm;j+)dataj=new doublen;,两种方法:释放二维数组,/方法1:delete score;/方法2:for(int i=0;im;i+)delete datai;delete data;,#includeusing namespace std;const int m=4;/行数const int n=6;/列数void desarray(double(*)6);/函数声明void main()double(*score)n;/定义二级指针变量 score=new doublemn;/一次分配全部数组单元 if(score=0)cout Could not allocate.;exit(-1);,【例2】动态创建和删除一个m*n个元素的数组。/方法一:采用指向二维数组的指针,一次分配,for(int i=0;im;i+)/初始化数组元素 for(int j=0;jn;j+)scoreij=i*n+j;for(i=0;im;i+)for(int j=0;jn;j+)coutscoreijt;coutendl;desarray(score);/调用函数撤消数组 return;,/二维数组的撤销与内存释放:void desarray(double(*score)n)delete score;,【例2】动态创建和删除一个m*n个元素的数组。/方法二:采用指针数组,二次分配,const int m=4;/行数const int n=6;/列数/先看二维数组的动态创建:void main()double*data;/定义指针数组,相当于*datam data=new double*m;/设置行指针 if(data)=0)cout Could not allocate.Bye.;exit(-1);for(int j=0;jm;j+)dataj=new doublen;/分配一个一维数组为一行 if(dataj=0)cout Could not allocate.Bye.;exit(-1);,for(int i=0;im;i+)for(int j=0;jn;j+)dataij=i*n+j;/初始化数组元素 print(data);/调用函数输出数据 destroy(data);/调用函数进行撤销与内存释放 return;/再看二维数组的撤销与内存释放:void destroy(double*data)for(int i=0;im;i+)delete datai;delete data;/注意撤销次序,与设置相反,指针使用的几个问题:1.动态分配失败。返回一个空指针(NULL),表示发生了异常,堆资源不足,分配失败。,2.指针删除与堆空间释放。删除一个指针p(delete p;)实际意思是删除了p所指的目标(变量或对象等),释放了它所占的堆空间,而不是删除本身,释放堆空间后,成了空悬指针。,内存泄漏(memory leak)和重复释放。new与delete 是配对使用的,delete只能释放堆空间。如果new返回的指针值丢失,则所分配的堆空间无法回收,称内存泄漏,同一空间重复释放也是危险的,因为该空间可能已另分配,所以必须妥善保存new返回的指针,以保证不发生内存泄漏,也必须保证不会重复释放堆内存空间。,动态分配的变量或对象的生命期。无名对象的生命期并不依赖于建立它的作用域,比如在函数中建立的动态对象在函数返回后仍可使用。我们也称堆空间为自由空间(free store)就是这个原因。但必须记住释放该对象所占堆空间,并只能释放一次,在函数内建立,而在函数外释放是一件很容易失控的事,往往会出错。,2.堆对象与构造函数,/动态创建对象class Point 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;,int main()coutStep One:endl;Point*Ptr1=new Point;/调用缺省构造函数 delete Ptr1;coutStep Two:endl;Ptr1=new Point(1,2);/调用带参构造函数 delete Ptr1;return 0;,运行结果:Step One:Default Constructor called.Destructor called.Step Two:Constructor called.Destructor called.,3.堆对象数组与构造函数,通过new建立的对象要调用构造函数,通过deletee删除对象也要调用析构函数。CGoods*pc;pc=new CGoods;/分配堆空间,并构造一个无名的CGoods对象;.delete pc;/先析构,然后将内存空间返回给堆;,堆对象的生命期并不依赖于建立它的作用域,所以除非程序结束,堆对象(无名对象)的生命期不会到期,并且需要显式地用delete语句析构堆对象,上面的堆对象在执行delete语句时,C+自动调用其析构函数。,class CGoods char Name21;int Amount;float Price;float Total value;public:CGoods();/缺省构造函数 CGoods(char*name,int amount,float price)strcpy(Name,name);Amount=amount;Price=price;Total_value=price*amount;/下面注意如何使用:,正因为构造函数可以有参数,所以new后面类(class)类型也可以有参数。这些参数即构造函数的参数。但对创建数组,则无参数,并只调用缺省的构造函数。见下例类说明:,下面注意如何使用:void main()int n;CGoods*pc,*pc1,*pc2;pc=new CGoods(“夏利2000”,10,118000);/调用三参数构造函数 pc1=new CGoods();/调用缺省构造函数 coutn;pc2=new CGoodsn;/动态建立数组,不能初始化,需调用n次缺省构造函数 delete pc;delete pc1;delete pc2;,例6-18 动态数组类,class ArrayOfPointsprivate:Point*points;int numberOfPoints;public:ArrayOfPoints(int n)numberOfPoints=n;points=new Pointn;/动态创建数组 ArrayOfPoints()coutDeleting.endl;numberOfPoints=0;delete points;Point,23,int main()int number;coutnumber;/创建对象数组 ArrayOfPoints points(number);/通过指针访问数组元素的成员 points.Element(0).Move(5,10);/通过指针访问数组元素的成员 points.Element(1).Move(15,20);,24,运行结果如下:Please enter the number of points:2Default Constructor called.Default Constructor called.Deleting.Destructor called.Destructor called.,25,堆对象与构造函数,这里再次强调:由堆区创建对象数组,只能调用缺省的构造函数,不能调用其他任何构造函数。如果没有缺省的构造函数,则不能创建对象数组。,4.浅拷贝与深拷贝,缺省拷贝构造函数,可用一个类对象初始化另一个类对象,称为缺省的按成员拷贝,而不是对整个类对象的按位拷贝。这称为浅拷贝。,如果类中有一个数据成员为指针,该类的一个对象obj1中的这个指针p,指向了动态分配的一个堆对象,(参见图7.1拷贝前),如果用obj1按成员拷贝了一个对象obj2,这时obj2.p也指向同一个堆对象。当析构时,如用缺省的析构函数,则动态分配的堆对象不能回收。如果在析构函数中有“delete p;”语句,则如果先析构函数obj1时,堆对象已经释放,以后再析构obj2时出现了二次释放的问题。这时就要重新定义拷贝的构造函数,给每个对象独立分配一个堆对象,称深拷贝。这时先拷贝对象主体,再为obj2分配一个堆对象,最后用obj1的堆对象拷贝obj2的堆对象。,浅拷贝与深拷贝,给每个对象独立分配一个堆对象,称深拷贝。这时先拷贝对象主体,再为obj2分配一个堆对象,最后用obj1的堆对象拷贝obj2的堆对象。,结论:,在类的某个数据成员为指针的情况下:浅拷贝实现对象间数据元素的一一对应复制。(只复制指针值)深拷贝当被复制的对象数据成员是指针类型时,不仅复制该指针成员本身,而且将指针所指的对象进行复制。指针成员指向新复制的单元。,例6-20 对象的浅拷贝,#includeusing namespace std;class Point/类的声明同例6-16/;class ArrayOfPoints/类的声明同例6-18/;,class Point 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;,class ArrayOfPoints public:ArrayOfPoints(int n)numberOfPoints=n;points=new Pointn;ArrayOfPoints()coutDeleting.endl;numberOfPoints=0;delete points;Point,int main()/观察浅拷贝的现象int number;cinnumber;ArrayOfPoints pointsArray1(number);pointsArray1.Element(0).Move(5,10);pointsArray1.Element(1).Move(15,20);ArrayOfPoints pointsArray2(pointsArray1);/拷贝构造 coutCopy of pointsArray1:endl;coutPoint_0 of array2:pointsArray2.Element(0).GetX(),pointsArray2.Element(0).GetY()endl;coutPoint_1 of array2:pointsArray2.Element(1).GetX(),pointsArray2.Element(1).GetY()endl;,34,pointsArray1.Element(0).Move(25,30);/数据改变 pointsArray1.Element(1).Move(35,40);coutAfter the moving of pointsArray1:endl;coutPoint_0 of array2:pointsArray2.Element(0).GetX(),pointsArray2.Element(0).GetY()endl;coutPoint_1 of array2:pointsArray2.Element(1).GetX(),pointsArray2.Element(1).GetY()endl;,35,运行结果如下:Please enter the number of points:2Default Constructor called.Default Constructor called.Copy of pointsArray1:Point_0 of array2:5,10Point_1 of array2:15,20After the moving of pointsArray1:Point_0 of array2:25,30Point_1 of array2:35,40Deleting.Destructor called.Destructor called.Deleting.接下来程序出现异常,也就是运行错误。,36,拷贝前,拷贝后,37,例6-21 对象的深拷贝,#includeusing namespace std;class Point/类的声明同例6-16;class ArrayOfPoints public:ArrayOfPoints(ArrayOfPoints,ArrayOfPoints:ArrayOfPoints(ArrayOfPointsint main()/同例6-20,39,程序的运行结果如下:Please enter the number of points:2Default Constructor called.Default Constructor called.Default Constructor called.Default Constructor called.Copy of pointsArray1:Point_0 of array2:5,10Point_1 of array2:15,20After the moving of pointsArray1:Point_0 of array2:5,10Point_1 of array2:15,20Deleting.Destructor called.Destructor called.Deleting.Destructor called.Destructor called.,40,拷贝前,拷贝后,pointsnumberOfPoints,pointsArray1,pointsArray1的数组元素占用的内存,pointsnumberOfPoints,pointsArray2,41,说明:堆内存是最常用的需要拷贝构造函数自定义的资源,但不是唯一的,如打开文件等。如果类需要析构函数来析构资源,则类也需要一个自定义的拷贝构造函数。对象的拷贝就是深拷贝了。,谢谢!,完,

    注意事项

    本文(re动态内存分配.ppt)为本站会员(牧羊曲112)主动上传,三一办公仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一办公(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    备案号:宁ICP备20000045号-2

    经营许可证:宁B2-20210002

    宁公网安备 64010402000987号

    三一办公
    收起
    展开