版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
《C++面向?qū)ο蟪绦蛟O(shè)計》教學(xué)內(nèi)容
第1章 C++概述第2章 類和對象第3章面向?qū)ο蟪绦蛟O(shè)計概述第4章深入學(xué)習(xí)類和對象第5章堆與復(fù)制結(jié)構(gòu)函數(shù)第6章繼承性:派生類第7章運算符重載第8章 虛函數(shù)和多態(tài)性第9章 模板第10章類庫和C++標準模板庫STL第11章輸入輸出流第12章異常處理第1頁第5章堆與復(fù)制結(jié)構(gòu)函數(shù)5.1堆5.2需要new和delete原因5.3默認復(fù)制結(jié)構(gòu)函數(shù)5.4自定義復(fù)制結(jié)構(gòu)函數(shù)第2頁5.1堆Heap堆是按動態(tài)方式分配內(nèi)存區(qū)域。在程序中需要空間存放數(shù)據(jù)時,就申請動態(tài)內(nèi)存單元,使用完成后釋放動態(tài)內(nèi)存單元。這種動態(tài)內(nèi)存分配方式能夠顯著地提升內(nèi)存利用率。第3頁C++程序內(nèi)存布局Stack棧Heap堆Globaldata全局數(shù)據(jù)區(qū)程序代碼區(qū)programcode代碼區(qū)存放程序代碼(可執(zhí)行指令);全局數(shù)據(jù)區(qū)存放全局變量、靜態(tài)變量、常量。固定存放區(qū)域棧是存放程序中全部動態(tài)局部變量、函數(shù)參數(shù)、函數(shù)返回值等信息一塊內(nèi)存區(qū)域。在固定存放區(qū)域與堆棧之間自由區(qū)域稱為堆第4頁棧Stack棧內(nèi)存管理嚴格遵照后進先出(LIFO:Lastin,FirstOut)次序,即釋放棧中對象所占內(nèi)存時次序剛好與給這些對象分配棧中內(nèi)存時次序相反,這一點正是實現(xiàn)函數(shù)調(diào)用所需要。從棧中分配內(nèi)存效率尤其高,對棧充分利用是C/C++編譯程序能產(chǎn)生優(yōu)質(zhì)高效代碼原因之一。第5頁動態(tài)內(nèi)存分配堆內(nèi)存是以動態(tài)分配方式管理。所謂動態(tài)分配內(nèi)存是在程序運行期間取得。動態(tài)存放分配方式允許我們程序能夠在執(zhí)行期間依據(jù)實際需要存放數(shù)據(jù)量來申請適當數(shù)量內(nèi)存單元。這種動態(tài)分配方式不但能夠提升內(nèi)存利用率,而且對于鏈表和二叉樹等動態(tài)數(shù)據(jù)結(jié)構(gòu)尤其有用。第6頁動態(tài)內(nèi)存申請和釋放用函數(shù)malloc()分配動態(tài)內(nèi)存必須用函數(shù)free()釋放;用new申請動態(tài)內(nèi)存必須用delete釋放。因為在C++程序中,從堆中獲取內(nèi)存單元不會被自動釋放,所以必須使用函數(shù)free()或者用delete釋放這種內(nèi)存。假如從堆中獲取內(nèi)存在使用完后沒有被釋放,這部分內(nèi)存在程序結(jié)束之前會一直被占用,這種情況被稱為“內(nèi)存泄漏”。第7頁5.2需要new和delete原因5.2.1需要new和delete原因5.2.2在堆上創(chuàng)建對象第8頁5.2.1需要new和delete原因?qū)ψ远x類類型,使用函數(shù)malloc()給對象分配動態(tài)空間時不能自動調(diào)用結(jié)構(gòu)函數(shù);使用函數(shù)free()釋放對象所占用動態(tài)空間時也不能調(diào)用析構(gòu)函數(shù)。C++語言創(chuàng)建了new和delete兩個運算符來滿足面向?qū)ο笮绿卣?,在C++語言程序中,我們應(yīng)該使用new和delete來創(chuàng)建和銷毀類對象。第9頁5.2.2在堆上創(chuàng)建對象使用new運算符在堆上創(chuàng)建對象時能夠自動調(diào)用結(jié)構(gòu)函數(shù)進行初始化;使用delete運算符釋放對象占用動態(tài)內(nèi)存時能夠自動調(diào)用該對象析構(gòu)函數(shù)進行善后處理。第10頁【例5.1】在堆上創(chuàng)建對象#include<iostream>usingnamespacestd;
classSquare{intside;public:Square(intx){side=x;cout<<"Constructiong\n";}~Square(){cout<<"Destructiong\n";}voiddisplay(){cout<<side<<"\n";}};第11頁【例5.1】在堆上創(chuàng)建對象(續(xù))intmain(){Square*ps=newSquare(10);//分配堆內(nèi)存并調(diào)用結(jié)構(gòu)函數(shù)初始化
ps->display();
deleteps;//自動調(diào)用析構(gòu)函數(shù),然后釋放堆內(nèi)存
return0;}該程序運行后輸出結(jié)果以下:Constructiong10Destructiong第12頁【例5.2】傳值調(diào)用例子classSquare{ intside;public: Square(intx){side=x;cout<<"Constructiong\n";} ~Square(){cout<<"Destructiong\n";} voiddisplay(){cout<<side<<"\n";}};voidf(Squareob)//對象作為函數(shù)參數(shù)
{ ob.display();}第13頁【例5.2】傳值調(diào)用例子(續(xù))intmain(){ Squares(10); f(s); //對象s以傳值方式傳送給暫時對象ob s.display(); return0;}該程序運行后輸出結(jié)果以下:Constructiong10DestructiongDestructiong10第14頁對象副本當一個對象被作為參數(shù)傳遞給函數(shù)時,同時也創(chuàng)建了該對象副本這個副本將成為函數(shù)參數(shù)。也就是說,創(chuàng)建了一個新對象。當函數(shù)結(jié)束時,作為函數(shù)實際參數(shù)副本將被銷毀。也就是說,一個對象被銷毀了第15頁兩個問題第一個問題:在創(chuàng)建對象副本時是否調(diào)用了結(jié)構(gòu)函數(shù)?第二個問題:當銷毀對象副本時是否調(diào)用了析構(gòu)函數(shù)?第16頁第一個問題答案首先,在調(diào)用函數(shù)時候,程序創(chuàng)建了一個對象副本作為形式參數(shù),此時普通結(jié)構(gòu)函數(shù)(normalconstructor)并沒有被調(diào)用,而是復(fù)制結(jié)構(gòu)函數(shù)(copyconstructor)被調(diào)用。第17頁為何需要復(fù)制結(jié)構(gòu)函數(shù)因為普通結(jié)構(gòu)函數(shù)通慣用于初始化對象一些組員,所以就不能調(diào)用普通結(jié)構(gòu)函數(shù)創(chuàng)建對象副本,因為這么產(chǎn)生對象可能與現(xiàn)有對象不完全相同。當把一個對象傳遞給函數(shù)時,我們需要使用是對象當前狀態(tài),而不是初始狀態(tài)第18頁5.3默認復(fù)制結(jié)構(gòu)函數(shù)復(fù)制結(jié)構(gòu)函數(shù)定義了怎樣創(chuàng)建一個對象副本。假如一個類中沒有顯式地定義類復(fù)制結(jié)構(gòu)函數(shù),那么C++將提供一個默認復(fù)制結(jié)構(gòu)函數(shù)(defaultcopyconstructor)。默認復(fù)制結(jié)構(gòu)函數(shù)將以按位復(fù)制形式創(chuàng)建一個對象副本,即創(chuàng)建一個與原對象一模一樣副本。第19頁第二個問題答案當函數(shù)結(jié)束時,因為作為參數(shù)對象副本超出了作用域,所以它將被銷毀,從而調(diào)用了析構(gòu)函數(shù)。第20頁結(jié)論當創(chuàng)建一個對象副本作為函數(shù)參數(shù)時,復(fù)制結(jié)構(gòu)函數(shù)被調(diào)用。當對象副本被銷毀時(通常因為函數(shù)返回而超出作用域),析構(gòu)函數(shù)被調(diào)用。第21頁自定義復(fù)制結(jié)構(gòu)函數(shù)例子Square(constSquare&ob){ side=ob.side; cout<<"CopyConstructiong\n";}假如程序員自定義了一個復(fù)制結(jié)構(gòu)函數(shù),編譯時將不會產(chǎn)生默認復(fù)制結(jié)構(gòu)函數(shù)。第22頁【例5.2】另一個版本classSquare{ intside;public: Square(intx){side=x;cout<<"Constructiong\n";} Square(constSquare&ob)//自定義復(fù)制結(jié)構(gòu)函數(shù) {side=ob.side;cout<<"CopyConstructiong\n";} ~Square(){cout<<"Destructiong\n";} voiddisplay(){cout<<side<<"\n";}};voidf(Squareob)//對象作為函數(shù)參數(shù)
{ ob.display();}第23頁【例5.2】另一個版本(續(xù))intmain(){ Squares(10); f(s); //對象s以傳值方式傳送給暫時對象ob s.display(); return0;}該程序運行后輸出結(jié)果以下:ConstructiongCopyConstructiong10Destructiong10Destructiong第24頁自定義復(fù)制結(jié)構(gòu)函數(shù)在很多情況下,使用按位復(fù)制方法來創(chuàng)建一個相同對象副本是可行,這時我們能夠直接使用C++語言提供默認復(fù)制結(jié)構(gòu)函數(shù)。不過,在一些情況下使用默認復(fù)制結(jié)構(gòu)函數(shù)會出現(xiàn)問題(比如【例5.3】),這時我們需要自己創(chuàng)建復(fù)制結(jié)構(gòu)函數(shù)。第25頁【例5.3】classmy_string{ char*s;public: my_string(char*str) { s=newchar[strlen(str)+1]; cout<<"Allocatingroomfors\n"; strcpy(s,str); } ~my_string() { if(s)delete[]s; cout<<"Freeings\n"; } voidshow() { cout<<s<<‘\n’; }};第26頁【例5.3】(續(xù))voiddisplay(my_stringob){ ob.show();}intmain(){ my_stringobj("Hello!"); display(obj); obj.show();//這條語句輸出是垃圾數(shù)據(jù) return0;}第27頁使用默認復(fù)制結(jié)構(gòu)函數(shù)出現(xiàn)了問題該程序運行后輸出結(jié)果以下:AllocatingroomforsHello!Freeings(撤消對象obj副本ob時調(diào)用析構(gòu)函數(shù))葺葺葺葺葺(這是輸出垃圾數(shù)據(jù),不一樣系統(tǒng)中輸出內(nèi)容會不相同)Freeings(撤消對象obj時調(diào)用析構(gòu)函數(shù))第28頁【例5.3】C++程序中對象內(nèi)存分布示意圖Hello實參對象obj形參對象ob(a)從函數(shù)display()返回前SS第29頁【例5.3】C++程序中對象內(nèi)存分布示意圖實參對象obj(b)從函數(shù)display()返回后S第30頁處理這個問題方法之一voiddisplay(my_string&ob){ ob.show();}經(jīng)過修改后,程序運行后輸出結(jié)果以下:AllocatingroomforsHello!Hello!Freeings防止復(fù)制對象第31頁初始化(initialization)(1)當一個對象副本被作為參數(shù)傳遞給函數(shù)時。my_stringy;display(y); //y被作為參數(shù)傳遞給函數(shù)當一個對象被另一個對象顯式地初始化時,比如在對象申明中。my_stringx=y;//對象y被顯式地用來初始化對象x(3) 當創(chuàng)建一個暫時對象時(最常見情況是作為函數(shù)返回值)。y=func2(); //y得到一個返回對象第32頁5.4.2復(fù)制結(jié)構(gòu)函數(shù)與函數(shù)參數(shù)當對象被作為參數(shù)傳遞給函數(shù)時,會產(chǎn)生該對象一個副本。假如我們創(chuàng)建了自定義復(fù)制結(jié)構(gòu)函數(shù),那么這個自定義復(fù)制結(jié)構(gòu)函數(shù)將被調(diào)用來制作這個對象副本。第33頁【例5.4】自定義復(fù)制結(jié)構(gòu)函數(shù)#include<iostream>#include<cstring>usingnamespacestd;classmy_string{ char*s;public: my_string(char*str);//普通結(jié)構(gòu)函數(shù) my_string(constmy_string&obj);
//自定義復(fù)制結(jié)構(gòu)函數(shù) ~my_string(){if(s)delete[]s;cout<<"Freeings\n";} voidshow(){cout<<s<<"\n";}};第34頁【例5.4】(續(xù)1)my_string::my_string(char*str) //普通結(jié)構(gòu)函數(shù){ s=newchar[strlen(str)+1]; cout<<"Allocatingroomfors\n"; strcpy(s,str);}my_string::my_string(constmy_string&obj)//自定義復(fù)制結(jié)構(gòu)函數(shù){ s=newchar[strlen(obj.s)+1]; strcpy(s,obj.s); cout<<"Copyconstructorcalled.\n"; }第35頁【例5.4】(續(xù)2)voiddisplay(my_stringob){ ob.show();}intmain(){ my_stringobj("Hello!"); display(obj); obj.show(); return0;}第36頁【例5.4】(續(xù)3)該程序運行后輸出結(jié)果以下:AllocatingroomforsCopyconstructorcalled.Hello!FreeingsHello!Freeings第37頁【例5.4】中C++程序?qū)ο髢?nèi)存分布示意圖Hello實參對象obj形參對象ob(a)從函數(shù)display()返回前SSHello第38頁【例5.4】C++程序中對象內(nèi)存分布示意圖實參對象obj(b)從函數(shù)display()返回后SHello第39頁5.4.3復(fù)制結(jié)構(gòu)函數(shù)與初始化當使用一個對象來初始化另一個對象時,也將調(diào)用復(fù)制結(jié)構(gòu)函數(shù)第40頁【例5.5】初始化對象時調(diào)用復(fù)制結(jié)構(gòu)函數(shù)。#include<iostream>#include<cstring>usingnamespacestd;classmy_string{ char*s;public: my_string(char*str);//普通結(jié)構(gòu)函數(shù)
my_string(constmy_string&obj);
//自定義復(fù)制結(jié)構(gòu)函數(shù) ~my_string(){if(s)delete[]s;cout<<"Freeings\n";} voidshow(){cout<<s<<"\n";}};第41頁【例5.5】(續(xù)1)my_string::my_string(char*str) //普通結(jié)構(gòu)函數(shù){ s=newchar[strlen(str)+1]; cout<<"Normalconstructorcalled.\n"; strcpy(s,str);}my_string::my_string(constmy_string&obj)
//自定義復(fù)制結(jié)構(gòu)函數(shù){ s=newchar[strlen(obj.s)+1]; strcpy(s,obj.s); cout<<"Copyconstructorcalled.\n";}第42頁【例5.5】(續(xù)2)intmain(){ my_stringobj("Hello!");//調(diào)用普通結(jié)構(gòu)函數(shù) my_stringob1(obj); //調(diào)用復(fù)制結(jié)構(gòu)函數(shù) my_stringob2=ob1; //調(diào)用復(fù)制結(jié)構(gòu)函數(shù) ob1.show(); ob2.show(); return0;}第43頁【例5.5】(續(xù)3)該程序運行后輸出結(jié)果以下:Normalconstructorcalled.Copyconstructorcalled.Copyconstructorcalled.Hello!Hello!FreeingsFreeingsFreeings第44頁復(fù)制結(jié)構(gòu)函數(shù)不會影響賦值運算記住,復(fù)制結(jié)構(gòu)函數(shù)只有在初始化對象時才被調(diào)用。比如,下面代碼將不會調(diào)用在前面程序中定義復(fù)制結(jié)構(gòu)函數(shù):my_strings1(“Hello”),s2(“world”);//…
s1=s2;賦值運算第45頁5.4.4在返回對象時使用復(fù)制結(jié)構(gòu)函數(shù)當函數(shù)返回對象時,函數(shù)創(chuàng)建了一個暫時對象來保留要返回值,而函數(shù)所返回對象實際上是這個暫時對象。在對象值被返回之后,暫時對象將被銷毀。在一些情況下,這會引發(fā)不可預(yù)料錯誤。第46頁【例5.6】函數(shù)返回對象#include<iostream>#include<cstring>usingnamespacestd;classmy_string{ char*s;public: my_string(char*str);//普通結(jié)構(gòu)函數(shù) ~my_string(){if(s)delete[]s;cout<<"Freeings\n";} voidshow(){cout<<s<<"\n";}};第47頁【例5.6】(續(xù)1)my_string::my_string(char*str) //普通結(jié)構(gòu)函數(shù){ s=newchar[strlen(str)+1]; cout<<"Normalconstructorcalled.\n"; strcpy(s,str);}my_stringinput()//返回一個my_string類型對象{ charinstr[80]; cout<<"Enterastring:"; cin>>instr; my_stringob(instr);//調(diào)用普通結(jié)構(gòu)函數(shù) returnob;}第48頁【例5.6】(續(xù)2)intmain(){ my_stringobj=input();//調(diào)用默認復(fù)制結(jié)構(gòu)函數(shù) //在函數(shù)input()中將調(diào)用普通結(jié)構(gòu)函數(shù) obj.show(); //輸出是垃圾數(shù)據(jù) return0;}該程序運行后輸出結(jié)果以下:Enterastring:HelloNormalconstructorcalled.Freeings葺葺葺葺葺葺葺葺葺葺輛@(這是輸出垃圾數(shù)據(jù),不一樣系統(tǒng)中輸出內(nèi)容會不相同)第49頁【例5.7】使用自定義復(fù)制結(jié)構(gòu)函數(shù)防止錯誤#include<iostream>#include<cstring>usingnamespacestd;classmy_string{ char*s;public: my_string(char*str);//普通結(jié)構(gòu)函數(shù) my_string(
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 辦公大樓幕墻施工安裝合同
- 電子元器件瑕疵管理方案
- 物業(yè)管理集團福利費管理手冊
- 家具行業(yè)項目招投標信息表
- 高空農(nóng)業(yè)噴灑合同
- 2025個人信用貸款借款合同
- 臨沂生態(tài)農(nóng)場租賃合同
- 門店市場調(diào)研渠道分析
- 醫(yī)用高值耗材管理指南
- 智能家居大清包施工合同
- 工地三相五線制電路布線詳解20160318
- 新《安全生產(chǎn)法》解讀PPT課件
- E車E拍行車記錄儀說明書 - 圖文-
- 人才梯隊-繼任計劃-建設(shè)方案(珍貴)
- WLANAP日常操作維護規(guī)范
- 《健身氣功》(選修)教學(xué)大綱
- GE公司燃氣輪機組支持軸承結(jié)構(gòu)及性能分析
- 《昆明的雨》優(yōu)質(zhì)課一等獎(課堂PPT)
- 油氣田地面建設(shè)工程ppt課件
- 電動蝶閥安裝步驟說明
- 全自動電鍍流水線操作說明書(共12頁)
評論
0/150
提交評論