堆與復(fù)制構(gòu)造函數(shù)省公開課一等獎(jiǎng)全國(guó)示范課微課金獎(jiǎng)?wù)n件_第1頁(yè)
堆與復(fù)制構(gòu)造函數(shù)省公開課一等獎(jiǎng)全國(guó)示范課微課金獎(jiǎng)?wù)n件_第2頁(yè)
堆與復(fù)制構(gòu)造函數(shù)省公開課一等獎(jiǎng)全國(guó)示范課微課金獎(jiǎng)?wù)n件_第3頁(yè)
堆與復(fù)制構(gòu)造函數(shù)省公開課一等獎(jiǎng)全國(guó)示范課微課金獎(jiǎng)?wù)n件_第4頁(yè)
堆與復(fù)制構(gòu)造函數(shù)省公開課一等獎(jiǎng)全國(guó)示范課微課金獎(jiǎng)?wù)n件_第5頁(yè)
已閱讀5頁(yè),還剩49頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

《C++面向?qū)ο蟪绦蛟O(shè)計(jì)》教學(xué)內(nèi)容

第1章 C++概述第2章 類和對(duì)象第3章面向?qū)ο蟪绦蛟O(shè)計(jì)概述第4章深入學(xué)習(xí)類和對(duì)象第5章堆與復(fù)制結(jié)構(gòu)函數(shù)第6章繼承性:派生類第7章運(yùn)算符重載第8章 虛函數(shù)和多態(tài)性第9章 模板第10章類庫(kù)和C++標(biāo)準(zhǔn)模板庫(kù)STL第11章輸入輸出流第12章異常處理第1頁(yè)第5章堆與復(fù)制結(jié)構(gòu)函數(shù)5.1堆5.2需要new和delete原因5.3默認(rèn)復(fù)制結(jié)構(gòu)函數(shù)5.4自定義復(fù)制結(jié)構(gòu)函數(shù)第2頁(yè)5.1堆Heap堆是按動(dòng)態(tài)方式分配內(nèi)存區(qū)域。在程序中需要空間存放數(shù)據(jù)時(shí),就申請(qǐng)動(dòng)態(tài)內(nèi)存單元,使用完成后釋放動(dòng)態(tài)內(nèi)存單元。這種動(dòng)態(tài)內(nèi)存分配方式能夠顯著地提升內(nèi)存利用率。第3頁(yè)C++程序內(nèi)存布局Stack棧Heap堆Globaldata全局?jǐn)?shù)據(jù)區(qū)程序代碼區(qū)programcode代碼區(qū)存放程序代碼(可執(zhí)行指令);全局?jǐn)?shù)據(jù)區(qū)存放全局變量、靜態(tài)變量、常量。固定存放區(qū)域棧是存放程序中全部動(dòng)態(tài)局部變量、函數(shù)參數(shù)、函數(shù)返回值等信息一塊內(nèi)存區(qū)域。在固定存放區(qū)域與堆棧之間自由區(qū)域稱為堆第4頁(yè)棧Stack棧內(nèi)存管理嚴(yán)格遵照后進(jìn)先出(LIFO:Lastin,FirstOut)次序,即釋放棧中對(duì)象所占內(nèi)存時(shí)次序剛好與給這些對(duì)象分配棧中內(nèi)存時(shí)次序相反,這一點(diǎn)正是實(shí)現(xiàn)函數(shù)調(diào)用所需要。從棧中分配內(nèi)存效率尤其高,對(duì)棧充分利用是C/C++編譯程序能產(chǎn)生優(yōu)質(zhì)高效代碼原因之一。第5頁(yè)動(dòng)態(tài)內(nèi)存分配堆內(nèi)存是以動(dòng)態(tài)分配方式管理。所謂動(dòng)態(tài)分配內(nèi)存是在程序運(yùn)行期間取得。動(dòng)態(tài)存放分配方式允許我們程序能夠在執(zhí)行期間依據(jù)實(shí)際需要存放數(shù)據(jù)量來(lái)申請(qǐng)適當(dāng)數(shù)量?jī)?nèi)存單元。這種動(dòng)態(tài)分配方式不但能夠提升內(nèi)存利用率,而且對(duì)于鏈表和二叉樹等動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)尤其有用。第6頁(yè)動(dòng)態(tài)內(nèi)存申請(qǐng)和釋放用函數(shù)malloc()分配動(dòng)態(tài)內(nèi)存必須用函數(shù)free()釋放;用new申請(qǐng)動(dòng)態(tài)內(nèi)存必須用delete釋放。因?yàn)樵贑++程序中,從堆中獲取內(nèi)存單元不會(huì)被自動(dòng)釋放,所以必須使用函數(shù)free()或者用delete釋放這種內(nèi)存。假如從堆中獲取內(nèi)存在使用完后沒有被釋放,這部分內(nèi)存在程序結(jié)束之前會(huì)一直被占用,這種情況被稱為“內(nèi)存泄漏”。第7頁(yè)5.2需要new和delete原因5.2.1需要new和delete原因5.2.2在堆上創(chuàng)建對(duì)象第8頁(yè)5.2.1需要new和delete原因?qū)ψ远x類類型,使用函數(shù)malloc()給對(duì)象分配動(dòng)態(tài)空間時(shí)不能自動(dòng)調(diào)用結(jié)構(gòu)函數(shù);使用函數(shù)free()釋放對(duì)象所占用動(dòng)態(tài)空間時(shí)也不能調(diào)用析構(gòu)函數(shù)。C++語(yǔ)言創(chuàng)建了new和delete兩個(gè)運(yùn)算符來(lái)滿足面向?qū)ο笮绿卣?,在C++語(yǔ)言程序中,我們應(yīng)該使用new和delete來(lái)創(chuàng)建和銷毀類對(duì)象。第9頁(yè)5.2.2在堆上創(chuàng)建對(duì)象使用new運(yùn)算符在堆上創(chuàng)建對(duì)象時(shí)能夠自動(dòng)調(diào)用結(jié)構(gòu)函數(shù)進(jìn)行初始化;使用delete運(yùn)算符釋放對(duì)象占用動(dòng)態(tài)內(nèi)存時(shí)能夠自動(dòng)調(diào)用該對(duì)象析構(gòu)函數(shù)進(jìn)行善后處理。第10頁(yè)【例5.1】在堆上創(chuàng)建對(duì)象#include<iostream>usingnamespacestd;

classSquare{intside;public:Square(intx){side=x;cout<<"Constructiong\n";}~Square(){cout<<"Destructiong\n";}voiddisplay(){cout<<side<<"\n";}};第11頁(yè)【例5.1】在堆上創(chuàng)建對(duì)象(續(xù))intmain(){Square*ps=newSquare(10);//分配堆內(nèi)存并調(diào)用結(jié)構(gòu)函數(shù)初始化

ps->display();

deleteps;//自動(dòng)調(diào)用析構(gòu)函數(shù),然后釋放堆內(nèi)存

return0;}該程序運(yùn)行后輸出結(jié)果以下:Constructiong10Destructiong第12頁(yè)【例5.2】傳值調(diào)用例子classSquare{ intside;public: Square(intx){side=x;cout<<"Constructiong\n";} ~Square(){cout<<"Destructiong\n";} voiddisplay(){cout<<side<<"\n";}};voidf(Squareob)//對(duì)象作為函數(shù)參數(shù)

{ ob.display();}第13頁(yè)【例5.2】傳值調(diào)用例子(續(xù))intmain(){ Squares(10); f(s); //對(duì)象s以傳值方式傳送給暫時(shí)對(duì)象ob s.display(); return0;}該程序運(yùn)行后輸出結(jié)果以下:Constructiong10DestructiongDestructiong10第14頁(yè)對(duì)象副本當(dāng)一個(gè)對(duì)象被作為參數(shù)傳遞給函數(shù)時(shí),同時(shí)也創(chuàng)建了該對(duì)象副本這個(gè)副本將成為函數(shù)參數(shù)。也就是說(shuō),創(chuàng)建了一個(gè)新對(duì)象。當(dāng)函數(shù)結(jié)束時(shí),作為函數(shù)實(shí)際參數(shù)副本將被銷毀。也就是說(shuō),一個(gè)對(duì)象被銷毀了第15頁(yè)兩個(gè)問(wèn)題第一個(gè)問(wèn)題:在創(chuàng)建對(duì)象副本時(shí)是否調(diào)用了結(jié)構(gòu)函數(shù)?第二個(gè)問(wèn)題:當(dāng)銷毀對(duì)象副本時(shí)是否調(diào)用了析構(gòu)函數(shù)?第16頁(yè)第一個(gè)問(wèn)題答案首先,在調(diào)用函數(shù)時(shí)候,程序創(chuàng)建了一個(gè)對(duì)象副本作為形式參數(shù),此時(shí)普通結(jié)構(gòu)函數(shù)(normalconstructor)并沒有被調(diào)用,而是復(fù)制結(jié)構(gòu)函數(shù)(copyconstructor)被調(diào)用。第17頁(yè)為何需要復(fù)制結(jié)構(gòu)函數(shù)因?yàn)槠胀ńY(jié)構(gòu)函數(shù)通慣用于初始化對(duì)象一些組員,所以就不能調(diào)用普通結(jié)構(gòu)函數(shù)創(chuàng)建對(duì)象副本,因?yàn)檫@么產(chǎn)生對(duì)象可能與現(xiàn)有對(duì)象不完全相同。當(dāng)把一個(gè)對(duì)象傳遞給函數(shù)時(shí),我們需要使用是對(duì)象當(dāng)前狀態(tài),而不是初始狀態(tài)第18頁(yè)5.3默認(rèn)復(fù)制結(jié)構(gòu)函數(shù)復(fù)制結(jié)構(gòu)函數(shù)定義了怎樣創(chuàng)建一個(gè)對(duì)象副本。假如一個(gè)類中沒有顯式地定義類復(fù)制結(jié)構(gòu)函數(shù),那么C++將提供一個(gè)默認(rèn)復(fù)制結(jié)構(gòu)函數(shù)(defaultcopyconstructor)。默認(rèn)復(fù)制結(jié)構(gòu)函數(shù)將以按位復(fù)制形式創(chuàng)建一個(gè)對(duì)象副本,即創(chuàng)建一個(gè)與原對(duì)象一模一樣副本。第19頁(yè)第二個(gè)問(wèn)題答案當(dāng)函數(shù)結(jié)束時(shí),因?yàn)樽鳛閰?shù)對(duì)象副本超出了作用域,所以它將被銷毀,從而調(diào)用了析構(gòu)函數(shù)。第20頁(yè)結(jié)論當(dāng)創(chuàng)建一個(gè)對(duì)象副本作為函數(shù)參數(shù)時(shí),復(fù)制結(jié)構(gòu)函數(shù)被調(diào)用。當(dāng)對(duì)象副本被銷毀時(shí)(通常因?yàn)楹瘮?shù)返回而超出作用域),析構(gòu)函數(shù)被調(diào)用。第21頁(yè)自定義復(fù)制結(jié)構(gòu)函數(shù)例子Square(constSquare&ob){ side=ob.side; cout<<"CopyConstructiong\n";}假如程序員自定義了一個(gè)復(fù)制結(jié)構(gòu)函數(shù),編譯時(shí)將不會(huì)產(chǎn)生默認(rèn)復(fù)制結(jié)構(gòu)函數(shù)。第22頁(yè)【例5.2】另一個(gè)版本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)//對(duì)象作為函數(shù)參數(shù)

{ ob.display();}第23頁(yè)【例5.2】另一個(gè)版本(續(xù))intmain(){ Squares(10); f(s); //對(duì)象s以傳值方式傳送給暫時(shí)對(duì)象ob s.display(); return0;}該程序運(yùn)行后輸出結(jié)果以下:ConstructiongCopyConstructiong10Destructiong10Destructiong第24頁(yè)自定義復(fù)制結(jié)構(gòu)函數(shù)在很多情況下,使用按位復(fù)制方法來(lái)創(chuàng)建一個(gè)相同對(duì)象副本是可行,這時(shí)我們能夠直接使用C++語(yǔ)言提供默認(rèn)復(fù)制結(jié)構(gòu)函數(shù)。不過(guò),在一些情況下使用默認(rèn)復(fù)制結(jié)構(gòu)函數(shù)會(huì)出現(xiàn)問(wèn)題(比如【例5.3】),這時(shí)我們需要自己創(chuàng)建復(fù)制結(jié)構(gòu)函數(shù)。第25頁(yè)【例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頁(yè)【例5.3】(續(xù))voiddisplay(my_stringob){ ob.show();}intmain(){ my_stringobj("Hello!"); display(obj); obj.show();//這條語(yǔ)句輸出是垃圾數(shù)據(jù) return0;}第27頁(yè)使用默認(rèn)復(fù)制結(jié)構(gòu)函數(shù)出現(xiàn)了問(wèn)題該程序運(yùn)行后輸出結(jié)果以下:AllocatingroomforsHello!Freeings(撤消對(duì)象obj副本ob時(shí)調(diào)用析構(gòu)函數(shù))葺葺葺葺葺(這是輸出垃圾數(shù)據(jù),不一樣系統(tǒng)中輸出內(nèi)容會(huì)不相同)Freeings(撤消對(duì)象obj時(shí)調(diào)用析構(gòu)函數(shù))第28頁(yè)【例5.3】C++程序中對(duì)象內(nèi)存分布示意圖Hello實(shí)參對(duì)象obj形參對(duì)象ob(a)從函數(shù)display()返回前SS第29頁(yè)【例5.3】C++程序中對(duì)象內(nèi)存分布示意圖實(shí)參對(duì)象obj(b)從函數(shù)display()返回后S第30頁(yè)處理這個(gè)問(wèn)題方法之一voiddisplay(my_string&ob){ ob.show();}經(jīng)過(guò)修改后,程序運(yùn)行后輸出結(jié)果以下:AllocatingroomforsHello!Hello!Freeings防止復(fù)制對(duì)象第31頁(yè)初始化(initialization)(1)當(dāng)一個(gè)對(duì)象副本被作為參數(shù)傳遞給函數(shù)時(shí)。my_stringy;display(y); //y被作為參數(shù)傳遞給函數(shù)當(dāng)一個(gè)對(duì)象被另一個(gè)對(duì)象顯式地初始化時(shí),比如在對(duì)象申明中。my_stringx=y;//對(duì)象y被顯式地用來(lái)初始化對(duì)象x(3) 當(dāng)創(chuàng)建一個(gè)暫時(shí)對(duì)象時(shí)(最常見情況是作為函數(shù)返回值)。y=func2(); //y得到一個(gè)返回對(duì)象第32頁(yè)5.4.2復(fù)制結(jié)構(gòu)函數(shù)與函數(shù)參數(shù)當(dāng)對(duì)象被作為參數(shù)傳遞給函數(shù)時(shí),會(huì)產(chǎn)生該對(duì)象一個(gè)副本。假如我們創(chuàng)建了自定義復(fù)制結(jié)構(gòu)函數(shù),那么這個(gè)自定義復(fù)制結(jié)構(gòu)函數(shù)將被調(diào)用來(lái)制作這個(gè)對(duì)象副本。第33頁(yè)【例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頁(yè)【例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頁(yè)【例5.4】(續(xù)2)voiddisplay(my_stringob){ ob.show();}intmain(){ my_stringobj("Hello!"); display(obj); obj.show(); return0;}第36頁(yè)【例5.4】(續(xù)3)該程序運(yùn)行后輸出結(jié)果以下:AllocatingroomforsCopyconstructorcalled.Hello!FreeingsHello!Freeings第37頁(yè)【例5.4】中C++程序?qū)ο髢?nèi)存分布示意圖Hello實(shí)參對(duì)象obj形參對(duì)象ob(a)從函數(shù)display()返回前SSHello第38頁(yè)【例5.4】C++程序中對(duì)象內(nèi)存分布示意圖實(shí)參對(duì)象obj(b)從函數(shù)display()返回后SHello第39頁(yè)5.4.3復(fù)制結(jié)構(gòu)函數(shù)與初始化當(dāng)使用一個(gè)對(duì)象來(lái)初始化另一個(gè)對(duì)象時(shí),也將調(diào)用復(fù)制結(jié)構(gòu)函數(shù)第40頁(yè)【例5.5】初始化對(duì)象時(shí)調(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頁(yè)【例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頁(yè)【例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頁(yè)【例5.5】(續(xù)3)該程序運(yùn)行后輸出結(jié)果以下:Normalconstructorcalled.Copyconstructorcalled.Copyconstructorcalled.Hello!Hello!FreeingsFreeingsFreeings第44頁(yè)復(fù)制結(jié)構(gòu)函數(shù)不會(huì)影響賦值運(yùn)算記住,復(fù)制結(jié)構(gòu)函數(shù)只有在初始化對(duì)象時(shí)才被調(diào)用。比如,下面代碼將不會(huì)調(diào)用在前面程序中定義復(fù)制結(jié)構(gòu)函數(shù):my_strings1(“Hello”),s2(“world”);//…

s1=s2;賦值運(yùn)算第45頁(yè)5.4.4在返回對(duì)象時(shí)使用復(fù)制結(jié)構(gòu)函數(shù)當(dāng)函數(shù)返回對(duì)象時(shí),函數(shù)創(chuàng)建了一個(gè)暫時(shí)對(duì)象來(lái)保留要返回值,而函數(shù)所返回對(duì)象實(shí)際上是這個(gè)暫時(shí)對(duì)象。在對(duì)象值被返回之后,暫時(shí)對(duì)象將被銷毀。在一些情況下,這會(huì)引發(fā)不可預(yù)料錯(cuò)誤。第46頁(yè)【例5.6】函數(shù)返回對(duì)象#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頁(yè)【例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()//返回一個(gè)my_string類型對(duì)象{ charinstr[80]; cout<<"Enterastring:"; cin>>instr; my_stringob(instr);//調(diào)用普通結(jié)構(gòu)函數(shù) returnob;}第48頁(yè)【例5.6】(續(xù)2)intmain(){ my_stringobj=input();//調(diào)用默認(rèn)復(fù)制結(jié)構(gòu)函數(shù) //在函數(shù)input()中將調(diào)用普通結(jié)構(gòu)函數(shù) obj.show(); //輸出是垃圾數(shù)據(jù) return0;}該程序運(yùn)行后輸出結(jié)果以下:Enterastring:HelloNormalconstructorcalled.Freeings葺葺葺葺葺葺葺葺葺葺輛@(這是輸出垃圾數(shù)據(jù),不一樣系統(tǒng)中輸出內(nèi)容會(huì)不相同)第49頁(yè)【例5.7】使用自定義復(fù)制結(jié)構(gòu)函數(shù)防止錯(cuò)誤#include<iostream>#include<cstring>usingnamespacestd;classmy_string{ char*s;public: my_string(char*str);//普通結(jié)構(gòu)函數(shù) my_string(

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論