第七章-動態(tài)內存分配--C++程序設計-計算機等級考試教學課件
*,計算機基礎教研室,*,單擊此處編輯母版標題樣式,單擊此處編輯母版文本樣式,第二級,第三級,第四級,第五級,第七章 動態(tài)內存分配,主講人:,XXX,電子郵件:,聯(lián)系電話:,2024/10/31,1,動態(tài)內存分配,本章首先介紹程序運行時,動態(tài)內存分配,(,dynamic memory allocation,)的概念與方法;再進一步討論復制構造函數(shù),.,7.1.1,自由存儲區(qū),內存,的分配與釋放,7.1.2,自由存儲區(qū),對象,與構造函數(shù),7.1.3,淺復制與深復制,2024/10/31,2,計算機基礎教研室,自由存儲區(qū)內存分配,靜態(tài)存儲分配:,無論全局或局部變量,(,對象,),,編譯器在,編譯時,都可以根據(jù)該變量,(,對象,),的類型知道所需內存空間的大小,從而系統(tǒng)在適當?shù)臅r候為它們分配確定的存儲空間。尤其是數(shù)組。,動態(tài)存儲分配:,有些操作對象只有在程序,運行時,才能確定,這樣編譯器在編譯時就無法為他們預定存儲空間,只能在程序運行時,系統(tǒng)根據(jù)運行時的要求進行內存分配,稱為動態(tài)存儲分配。動態(tài)分配都在,自由存儲區(qū),中進行。,2024/10/31,3,計算機基礎教研室,自由存儲區(qū),內存的分配與釋放,當程序運行到需要動態(tài)分配變量或對象時,必須向系統(tǒng),申請取得自由存儲區(qū),中的一塊所需大小的存貯空間,用于存貯該變量或對象。當不再使用該變量或對象時,也就是它的生命結束時,要,顯式釋放,它所占用的存貯空間,這樣系統(tǒng)就能進行再次分配,做到重復使用有限的資源。,動態(tài)分配與釋放:,2024/10/31,4,計算機基礎教研室,一般定義變量和對象時要用標識符命名,稱,命名對象,,而動態(tài)的稱,無名對象,(,請注意與棧區(qū)中的臨時對象的區(qū)別,兩者完全不同:生命期不同,操作方法不同,臨時變量對程序員是透明的,),。,自由存儲區(qū),是不會自動在分配時做初始化的(包括清零),所以必須用初始化式,(initializer),來顯式初始化。,無名對象:,自由存儲區(qū),內存的分配與釋放,2024/10/31,6,計算機基礎教研室,new,表達式的操作:,從自由存儲區(qū)分配對象,然后用括號中的值初始化該對象,。,分配對象時,,new,表達式調用庫操作符,new,(),:,int,*pi=,new,int,(0);,pi,現(xiàn)在所指向的變量的存儲空間是由庫操作符,new,(),分配的,位于程序的自由存儲區(qū)中,并且該對象未命名。,自由存儲區(qū),內存的分配與釋放,2024/10/31,7,計算機基礎教研室,自由存儲區(qū),i,演示:,用初始化式,(initializer),來顯式初始化,int,*pi=,new,int,(0);,當,pi,生命周期結束時,,必須釋放,pi,所指向的目標:,delete,pi;,注意這時釋放了,pi,所指的目標的內存空間,也就是撤銷了該目標,稱動態(tài)內存釋放(,dynamic memory deallocation,),但,指針,pi,本身并沒有撤銷,,該指針所占內存空間并未釋放。,自由存儲區(qū),內存的分配與釋放,2024/10/31,8,計算機基礎教研室,動態(tài)分配數(shù)組與,標準字符串類,:,標準字符串類,string,就是采用動態(tài)建立數(shù)組的方式解決數(shù)組溢出的問題的,例,7.1,所做的動態(tài)內存分配與釋放,在,string,類對象中都是自動完成的,在程序中不需要也不允許再顯式地為,string,進行動態(tài)內存的分配與釋放。,【,例,7.1】,動態(tài)數(shù)組的建立與撤銷,自由存儲區(qū),內存的分配與釋放,2024/10/31,10,計算機基礎教研室,【,例,7.1,】,動態(tài)數(shù)組的建立與撤銷,#include,#include,using namespace,std,;,int,main(),int,n;,char,*pc;,cout,請輸入動態(tài)數(shù)組的元素個數(shù),n;,/,在運行時確定,可輸入,25,pc=,new char,n;,strcpy(pc,自由存儲區(qū)內存的動態(tài)分配,);,coutpcendl;,delete,pc;,/,釋放,pc,所指向的,n,個字符的內存空間,return,0;,2024/10/31,11,計算機基礎教研室,1.,動態(tài)分配失敗,。返回一個空指針(,NULL,),表示發(fā)生了異常,堆資源不足,分配失敗。,2.,指針刪除與自由存儲區(qū)空間釋放,。刪除一個指針,p,(,delete,p;,)實際意思是刪除了,p,所指的目標(變量或對象等),釋放了它所占的自由存儲區(qū)空間,而不是刪除本身,釋放自由存儲區(qū)空間后,成了空懸指針。空懸指針是程序錯誤的一個根源)。建議這時將置空(,NULL,)。,自由存儲區(qū),內存的分配與釋放,指針使用的要點:,2024/10/31,13,計算機基礎教研室,5,內存泄漏(,memory leak,)和重復釋放,。,new,與,delete,是配對使用的,,delete,只能釋放,自由存儲區(qū),空間。如果,new,返回的指針值丟失,則所分配的,自由存儲區(qū),空間無法回收,稱內存泄漏,同一空間重復釋放也是危險的,因為,該空間可能已另分配,,所以必須妥善保存,new,返回的指針,以保證不發(fā)生內存泄漏,也必須保證不會重復釋放,自由存儲區(qū),內存空間。,自由存儲區(qū),內存的分配與釋放,指針使用的要點:,2024/10/31,15,計算機基礎教研室,自由存儲區(qū),對象與構造函數(shù),類對象動態(tài)建立與刪除過程:,通過,new,建立的對象要調用構造函數(shù),通過,delete,刪除對象也要調用析構函數(shù)。,CGoods*pc;,pc=new CGoods;,/,分配自由存儲區(qū)空間,并構造一個無名的,CGoods,對象;,.,delete pc;,/,先析構,然后將內存空間返回給自由存儲區(qū);,自由存儲區(qū),對象的生命期并不依賴于建立它的作用域,所以除非程序結束,,自由存儲區(qū),對象(無名對象)的生命期不會到期,并且需要顯式地用,delete,語句析構該類對象,上例執(zhí)行,delete,語句時,,C+,自動調用商品類的析構函數(shù)。,2024/10/31,16,計算機基礎教研室,類說明:,class,CGoods,string Name;,int,Amount;,float,Price;,float,Total_value;,public:,CGoods()cout,調用默認構造函數(shù),endl;,CGoods(string name,int,amount,float,price),cout,調用三參數(shù)構造函數(shù),endl;,Name=name;Amount=amount;,Price=price;Total_value=price*amount;,CGoods()cout,調用析構函數(shù),endl;,;,【,例,7.3】,演示自由存儲區(qū)對象分配和釋放。,2024/10/31,18,計算機基礎教研室,使用:,int,main(),int,n;,CGoods*pc,*pc1,*pc2;,pc=,new,CGoods(,“,夏利,2000,”,,,10,,,118000);,/,調用三參數(shù)構造函數(shù),pc1=,new,CGoods();,/,調用默認構造函數(shù),cout,輸入商品類數(shù)組元素數(shù),n;,pc2=,new,CGoodsn;,/,動態(tài)建立數(shù)組,不能初始化,調用,n,次默認構造函數(shù),delete,pc;,delete,pc1;,delete,pc2;,return,0;,2024/10/31,19,計算機基礎教研室,例,6-16,動態(tài)創(chuàng)建對象舉例,#include,using namespace std;,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;,;,2024/10/31,20,計算機基礎教研室,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.,21,例,6-16,動態(tài)創(chuàng)建對象舉例,2024/10/31,21,計算機基礎教研室,淺復制(淺拷貝),實現(xiàn)對象間數(shù)據(jù)元素的一一對應復制。,深復制(深拷貝),當被復制的對象數(shù)據(jù)成員是指針類型時,不是復制該指針成員本身,而是將指針所指的對象進行復制。,淺復制與深復制,2024/10/31,22,計算機基礎教研室,當,淺復制,析構時,如用默認的析構函數(shù),則動態(tài)分配的,自由存儲區(qū),對象不能回收。如果在析構函數(shù)中有“,delete p;,”,語句,則如果先析構函數(shù),obj1,時,,自由存儲區(qū),對象已經(jīng)釋放,以后再析構,obj2,時出現(xiàn)了二次釋放的問題。,自由存儲區(qū),對象,P,P,自由存儲區(qū),對象,圖,7.2,深復制,深復制:,重新定義復制的構造函數(shù),給每個對象獨立分配一個,自由存儲區(qū),對象,稱,深復制,。,這時先復制對象主體,再為,obj2,分配一個,自由存儲區(qū),對象,最后用,obj1,的,自由存儲區(qū),對象復制,obj2,的,自由存儲區(qū),對象。,obj1,obj2,淺復制與深復制,2024/10/31,24,計算機基礎教研室,淺復制與深復制,【,例,7.4】,定義復制構造函數(shù),(,copy structor,)和復制賦值操作符(,copy Assignment Operator,)實現(xiàn)深復制。,學生類定義:,class,student,char,*pName;,/,為了演示深復制,不用,string,類,public,:,student();,/,默認構造函數(shù),student(char*pname);,/,帶參數(shù),構造函數(shù),student(student,/,復制構造函數(shù),student();,/,析構函數(shù),student&,operator,=(student,/,復制賦值操作符,檢驗,主函數(shù),和,運行結果,2024/10/31,25,計算機基礎教研室,例,7.4,實現(xiàn)深復制,默認構造函數(shù):,student:student(),coutConstructor;,pName=NULL;,cout,默認“,endl;,帶參數(shù),構造函數(shù):,student:student(,char,*pname),coutConstructor;,if,(pName=,new,char,strlen(pname)+1),strcpy(pName,pname);,coutpNameendl;,2024/10/31,26,計算機基礎教研室,例,7.4,實現(xiàn)深復制,復制賦值操作符:,student&student:,operator,=(student&s),coutCopy Assign operator;,delete,pName,;/,如原來已分配,應先撤銷,再重分配,if,(s.pName),/,否則會發(fā)生內存泄漏,if,(pName=,new,char,strlen(s.pName)+1),strcpy(pName,s.pName);,else,pName=NULL;,coutpNameendl;,return,*,this,;,2024/10/31,28,計算機基礎教研室,例,7.4,實現(xiàn)深復制,int,main(,void,),student s1(,范英明,),s2(,沈俊,),s3;,studen