C程序設(shè)計(jì)課件:第14章 堆與拷貝構(gòu)造函數(shù)_第1頁(yè)
C程序設(shè)計(jì)課件:第14章 堆與拷貝構(gòu)造函數(shù)_第2頁(yè)
C程序設(shè)計(jì)課件:第14章 堆與拷貝構(gòu)造函數(shù)_第3頁(yè)
C程序設(shè)計(jì)課件:第14章 堆與拷貝構(gòu)造函數(shù)_第4頁(yè)
C程序設(shè)計(jì)課件:第14章 堆與拷貝構(gòu)造函數(shù)_第5頁(yè)
已閱讀5頁(yè),還剩39頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、 第十四章 堆與拷貝構(gòu)造函數(shù)2本章主要內(nèi)容 14.1 關(guān)于堆 14.2 需要new和delete的原因 14.3 分配堆對(duì)象 14.4 拷貝構(gòu)造函數(shù) 14.5 默認(rèn)拷貝構(gòu)造函數(shù) 14.6 淺拷貝與深拷貝 14.7 臨時(shí)對(duì)象 14.8 無(wú)名對(duì)象 14.9 構(gòu)造函數(shù)用于類(lèi)型轉(zhuǎn)換 作業(yè)314.1 關(guān)于堆C+程序的內(nèi)存格局: (1) 全局?jǐn)?shù)據(jù)區(qū):存放全局變量、靜態(tài)數(shù)據(jù)、常量; (2) 代碼區(qū):存放所有類(lèi)成員函數(shù)和非成員函數(shù)代碼; (3) 棧區(qū):存放為運(yùn)行函數(shù)而分配的局部變量、函數(shù)參數(shù)、返回?cái)?shù)據(jù)、返回地址等; (4) 堆區(qū):余下的空間,動(dòng)態(tài)分配。414.1 關(guān)于堆函數(shù): void* malloc(siz

2、e_t); /從堆中分配內(nèi)存 void free(void *); /釋放由malloc申請(qǐng)的堆內(nèi)存操作符: new /從堆中分配內(nèi)存 delete /釋放由new分配的堆內(nèi)存兩種方法都可以從堆中分配和釋放內(nèi)存,但二者在具體操作上有很大區(qū)別。堆內(nèi)碎塊:堆區(qū)內(nèi)眾多不連續(xù)的內(nèi)存小塊。動(dòng)態(tài)分配內(nèi)存應(yīng)注意:及時(shí)釋放內(nèi)存,避免堆區(qū)碎塊。514.2 需要new和delete的原因C+ :對(duì)象建立時(shí)應(yīng)通過(guò)構(gòu)造函數(shù)分配空間、構(gòu)造數(shù)據(jù)結(jié)構(gòu)、初始化數(shù)據(jù)。而用malloc()函數(shù)分配空間時(shí),不自動(dòng)調(diào)用構(gòu)造函數(shù);free()函數(shù)也不自動(dòng)調(diào)用析構(gòu)函數(shù)。所以,需要增加操作符:new和delete,完成C+規(guī)定的操作。61

3、4.2 需要new和delete的原因例如,下面的代碼用malloc()分配空間: class Tdate public: Tdate( ); void SetDate(int m=1, int d=1, int y=1998); protected: int month; int day; int year; ; 714.2 需要new和delete的原因 Tdate:Tdate() month=1; day=1; year=1900; void Tdate:SetDate(int m, int d, int y) if (m0 & m0 & d0 & y0 & m0 & d0 & y300

4、0) year=y; void fn( ) Tdate * pD; pD=new Tdate(1,1,1998); /自動(dòng)調(diào)用帶參構(gòu)造函數(shù) / delete (pD); /自動(dòng)調(diào)用析構(gòu)函數(shù) 1314.3 分配堆對(duì)象下面的代碼分配了參數(shù)給定的對(duì)象個(gè)數(shù),并在函數(shù)結(jié)束時(shí)予以返還: class Student public: Student(char* pName=no name) strncpy(name,pName,sizeof(name); namesizeof(name)-1=0; protected: char name40; ; void fn(int noOfObjects) Stude

5、nt * pS=new Student noOfObjects ; / delete pS; 從堆上分配對(duì)象數(shù)組,只能調(diào)用默認(rèn)構(gòu)造函數(shù),不能調(diào)用其他任何構(gòu)造函數(shù)。#includestatic int k;class A private: int x,y; public: A(int xx=0,int yy=0):x(xx+k),y(yy+k) k+; coutAx yendl; A( )coutAx yendl; void put( ) coutx yendl; ; int main() int *p1, *p2=new int(789), *p3=new int10; p1=new int;

6、 *p1=123; cout*p1 *p2endl; for(int i=0;i10;i+) p3i=i+1; for(int j=0;j10;j+) coutp3j ; coutendl; A *pa1=new A(555,777), *pa2=new A2; coutput( ) : ; pa1-put( ); coutput( ) : ; pa2-put( ); coutput( ) : ; (pa2+1)-put( ); delete pa1; delete pa2; 執(zhí)行結(jié)果: 123 789 1 2 3 4 5 6 7 8 9 10 A. 555 777 A. 1 1 A. 2 2

7、 pa1-put() : 555 777 pa2-put() : 1 1 (pa2+1)-put( ) : 2 2 A555 777 A 2 2 A 1 1說(shuō)明: 1.動(dòng)態(tài)分配堆數(shù)組對(duì)象時(shí),不能對(duì)數(shù)組進(jìn)行初始化 2.動(dòng)態(tài)分配堆數(shù)組對(duì)象時(shí),每維的大小必須指定,不能缺省 1714.4 拷貝構(gòu)造函數(shù)拷貝構(gòu)造函數(shù):特殊的構(gòu)造函數(shù)作用:當(dāng)用一個(gè)已存在的對(duì)象構(gòu)造一個(gè)新的對(duì)象時(shí),或者說(shuō),用另一個(gè)對(duì)象值初始化一個(gè)新構(gòu)造的對(duì)象,系統(tǒng)不自動(dòng)調(diào)用構(gòu)造函數(shù),而是自動(dòng)調(diào)用拷貝構(gòu)造函數(shù),創(chuàng)建新的對(duì)象,并把對(duì)象的數(shù)據(jù)成員值復(fù)制給新的對(duì)象(在編譯時(shí)進(jìn)行)。 (); =;TDate a(3);TDate b(a);/TDate

8、 b=a;1814.4 拷貝構(gòu)造函數(shù)拷貝構(gòu)造函數(shù)聲明的一般形式: 類(lèi)名(const 類(lèi)名& 形參對(duì)象名);拷貝構(gòu)造函數(shù)定義的一般形式: 類(lèi)名:類(lèi)名(const 類(lèi)名& 形參對(duì)象名) / 1914.4 拷貝構(gòu)造函數(shù)Page 19拷貝構(gòu)造函數(shù)被調(diào)用的3種情況:1. 新建對(duì)象: class A; int main( ) A a; A a1(a); 2. 實(shí)參傳遞給形參時(shí): void f(A a1) int main( ) A a; f(a); 3. 函數(shù)返回時(shí): A fn( ) A a; / return a; int main( ) A a2=fn(); 20#include #include c

9、lass Student protected: char name40; int id; public: Student(char* pName=no name, int ssId=0) id = ssId; strcpy(name,pName); coutConstructing new student pName endl; Page 2014.4 拷貝構(gòu)造函數(shù)21 Student(Student& s) /拷貝構(gòu)造函數(shù) cout Constructing copy of endl; strcpy(name,copy of ); strcat(name, ); i

10、d=s.id; Student( ) cout Destructing name endl;void fn(Student s1) cout In function fn()n; int main( ) Student randy(Randy,1234); cout Calling fn()n; fn(randy); cout Returned from fn()n; Page 2114.4 拷貝構(gòu)造函數(shù)22運(yùn)行結(jié)果為: Constructing new student Randy /: Randy Calling fn() Constructing copy of Ran

11、dy /: copy of Randy In function fn() Destructing copy of Randy /釋放s對(duì)象 Returned from fn( ) Destructing Randy /釋放randy對(duì)象Page 2214.4 拷貝構(gòu)造函數(shù)23如果類(lèi)定義中沒(méi)有定義拷貝構(gòu)造函數(shù),系統(tǒng)自動(dòng)為類(lèi)提供一個(gè)默認(rèn)的拷貝構(gòu)造函數(shù)。C+提供的默認(rèn)拷貝構(gòu)造函數(shù)工作的方法是,完成一個(gè)成員一個(gè)成員的拷貝。如果成員是類(lèi)對(duì)象,則調(diào)用其拷貝構(gòu)造函數(shù)或者默認(rèn)拷貝構(gòu)造函數(shù)。一般情況下,不必定義拷貝構(gòu)造函數(shù)。但是,如果構(gòu)造函數(shù)中存在動(dòng)態(tài)分配,則必須定義拷貝構(gòu)造函數(shù)(見(jiàn)14.6節(jié))。

12、Page 2314.5 默認(rèn)拷貝構(gòu)造函數(shù)24#include #include class Student protected: char name40; public: Student(char* pName=no name) /構(gòu)造函數(shù) cout Constructing new student pNameendl; strncpy(name,pName,sizeof(name); namesizeof(name)-1=0; Student(Student& s) /拷貝構(gòu)造函數(shù) cout Constructing copy of endl; strcpy(name,copy

13、 of ); strcat(name,); Student( ) cout Destructing name endl; ; 14.5 默認(rèn)拷貝構(gòu)造函數(shù)25class Tutor protected: Student student; public: Tutor(Student& s):student(s) /帶參構(gòu)造函數(shù) cout Constructing tutorn; Tutor()cout “Destructing tutor”endl; ;void fn(Tutor tutor1) cout In function fn( )n; int main( ) Student

14、randy(Randy); / Tutor tutor(randy); / cout Calling fn()n; / fn(tutor); / cout Returned from fn()n; / 14.5 默認(rèn)拷貝構(gòu)造函數(shù)運(yùn)行結(jié)果: Constructing new student Randy / 值為: Randy Constructing copy of Randy / 值為: copy of Randy Constructing tutor Calling fn() Constructing copy of copy of

15、Randy / 值為: copy of copy of Randy In function fn() Destructing tutor Destructing copy of copy of Randy /釋放fn中的對(duì)象tutor1的空間 Returned from fn() Destructing tutor Destructing copy of Randy /釋放main中的對(duì)象tutor的空間 Destructing Randy /釋放main中的對(duì)象randy的空間 Page 262714.6 淺拷貝與深拷貝淺拷貝:拷貝成員,不拷貝資源 。

16、默認(rèn)拷貝構(gòu)造函數(shù)是淺拷貝方式。例: #include #include class Person protected: char* pName; public: Person(char* pN) cout Constructing pN endl; pName=new charstrlen(pN)+1; if(pName!=0) strcpy(pName, pN); Page 2728 Person( ) cout Destructing pNameendl; pName0=0; delete pName; ;int main( ) Person p1(Randy); Person p2=p1

17、; /即Person p2(p1);運(yùn)行結(jié)果: Constructing Randy Destructing Randy Destructing Null pointer assignment14.6 淺拷貝與深拷貝29 pName堆拷貝前pNamepName堆拷貝后圖14-2 p1p2的淺拷貝p1p2p114.6 淺拷貝與深拷貝30深拷貝:拷貝成員,也拷貝資源。對(duì)于數(shù)據(jù)成員有指針類(lèi)型的類(lèi)來(lái)說(shuō),必須自己定義一個(gè)拷貝構(gòu)造函數(shù),在數(shù)值拷貝之前,需要為指針類(lèi)型的數(shù)據(jù)成員另辟一個(gè)獨(dú)立的內(nèi)存空間,這就是深拷貝。 #include #include class Person public: Person(

18、char* pN); Person(Person& p); Person( ); protected: char* pName; ;14.6 淺拷貝與深拷貝 Person:Person(char* pN) cout Constructing pN endl; pName=new charstrlen(pN)+1; if(pName!=0) strcpy(pName, pN); Person:Person(Person& p) cout Copying p.pName into its own blockn; pName=new charstrlen(p.pName)+1; if(pName!=

19、0) strcpy(pName, p.pName); Person:Person( ) cout Destructing pName endl; pName0=0; delete pName;int main( ) Person p1(Randy); Person p2=p1; /即Person p2(p1); 運(yùn)行結(jié)果: Constructing Randy Copying Randy into its own block Destructing Randy Destructing Randy32 pName堆拷貝前pNamepName堆拷貝后圖14-3 p1p2的深拷貝堆p1p2p114.

20、6 淺拷貝與深拷貝33堆內(nèi)存并不是唯一需要拷貝構(gòu)造函數(shù)的資源,但它是最常用的一個(gè)。打開(kāi)文件,占有硬設(shè)備(例如打印機(jī))服務(wù)等也需要深拷貝。它們也是析構(gòu)函數(shù)必須返還的資源類(lèi)型。因此,如果類(lèi)對(duì)象需要用析構(gòu)函數(shù)來(lái)析構(gòu)資源,必須定義具有析構(gòu)資源功能的拷貝構(gòu)造函數(shù)。14.6 淺拷貝與深拷貝3414.7 臨時(shí)對(duì)象當(dāng)函數(shù)返回一個(gè)對(duì)象時(shí),要?jiǎng)?chuàng)建一個(gè)臨時(shí)對(duì)象以存放到返回的對(duì)象。例:Student fn( ) / Student ms(“Randy”) ; return ms; int main( ) Student s; s=fn( ); / 35 ms函數(shù)main棧區(qū)函數(shù)fn棧區(qū)取出放入臨時(shí)對(duì)象s圖14-4 返

21、回對(duì)象的函數(shù)運(yùn)行結(jié)束時(shí)14.7 臨時(shí)對(duì)象36一般規(guī)定,創(chuàng)建的臨時(shí)對(duì)象,在整個(gè)創(chuàng)建它們的外部表達(dá)式范圍內(nèi)有效,否則無(wú)效。例:下面的代碼中,引用refs不再有效 int main( ) Student & refs=fn( ); /refs是臨時(shí)對(duì)象的引用 / refs.GetName( ); /error臨時(shí)對(duì)象已經(jīng)不再有效 14.7 臨時(shí)對(duì)象37又例如,下面的代碼中,一切臨時(shí)對(duì)象都在一個(gè)外部表達(dá)式中結(jié)束: Student fn1( ); int fn2(Student &); int main( ) int x; x=3*fn2(fn1( )*10; /*fn1()返回時(shí),創(chuàng)建臨時(shí)對(duì)象作為fn

22、2()的實(shí)參, 此時(shí), 在fn2()中一直有效;當(dāng)fn2()返回一個(gè)int值參與 計(jì)算表達(dá)式時(shí),那個(gè)臨時(shí)對(duì)象仍有效;一旦計(jì)算 完成,賦值給x后,則臨時(shí)對(duì)象被析構(gòu)。*/ / 14.7 臨時(shí)對(duì)象3814.8 無(wú)名對(duì)象無(wú)名對(duì)象:實(shí)際存在、但沒(méi)有標(biāo)識(shí)符的對(duì)象??梢岳脴?gòu)造函數(shù)創(chuàng)建無(wú)名對(duì)象。 例: class Student public: Student (char*); / ; void fn( ) Student(“Randy”); /此處為無(wú)名對(duì)象 / 39無(wú)名對(duì)象的3種用法:初始化一個(gè)“引用”、 拷貝構(gòu)造一個(gè)新對(duì)象、函數(shù)的實(shí)參。例如,下面的代碼表達(dá)了無(wú)名對(duì)象典型的三種用法: void fn(S

23、tudent & s); Student & refs=Student(“Randy”); /初始化引用主函數(shù)運(yùn)行時(shí),此語(yǔ)句執(zhí)行的是用無(wú)名對(duì)象初始化一個(gè)引用。由于是在函數(shù)內(nèi)部,所以無(wú)名對(duì)象作為局部對(duì)象產(chǎn)生在??臻g中,從作用域上看,該引用與無(wú)名對(duì)象是相同的,完全等價(jià)與Student refs=“Randy”; 所以這種使用是多余的。14.8 無(wú)名對(duì)象40Student s=Student(“Jenny”); /初始化對(duì)象定義此語(yǔ)句執(zhí)行的是用無(wú)名對(duì)象拷貝構(gòu)造一個(gè)對(duì)象s。而拷貝完后,無(wú)名對(duì)象就失去了任何作用,對(duì)于這種情況,C+特別地將其看作為Student s=“Jenny”;效果一樣,而且可以省略創(chuàng)建無(wú)名對(duì)象這一步。fn(Stu

溫馨提示

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

評(píng)論

0/150

提交評(píng)論