




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
2024/8/121動態(tài)內(nèi)存管理技術(shù)
C++常見問題132Const的使用內(nèi)聯(lián)函數(shù)的使用使用引用4類型轉(zhuǎn)換5異常處理6命名空間7內(nèi)容提要2024/8/1226.1內(nèi)聯(lián)函數(shù)的使用6.1.1內(nèi)聯(lián)函數(shù)引入的原因調(diào)用函數(shù)時,要跳到函數(shù)的起始地址去執(zhí)行,執(zhí)行完函數(shù)的代碼后,再返回到調(diào)用點繼續(xù)執(zhí)行。這種跳轉(zhuǎn)操作需要保存現(xiàn)場及返回地址;返回時,又需要恢復(fù)現(xiàn)場。函數(shù)調(diào)用需要一定的時間開銷和空間開銷,這會影響程序的執(zhí)行效率。外聯(lián)開銷2024/8/123對內(nèi)聯(lián)函數(shù),編譯器會在程序出現(xiàn)內(nèi)聯(lián)函數(shù)調(diào)用的地方用函數(shù)體直接進(jìn)行替換。目標(biāo)程序?qū)⒉淮嬖谡{(diào)用問題,也就不會產(chǎn)生跳轉(zhuǎn)的問題,自然就不存在函數(shù)調(diào)用所需要的時間和空間開銷。在編譯時用函數(shù)代碼替換到調(diào)用處,如果函數(shù)代碼長度比較長,超過了跳轉(zhuǎn)語句所占空間的長度,這自然會增加整個程序的代碼量,進(jìn)而增加了空間的開銷。實質(zhì)是用空間換時間。6.1內(nèi)聯(lián)函數(shù)的使用2024/8/1246.1.2內(nèi)聯(lián)函數(shù)的定義例6_1:smain6_1.cpp
//1、全局函數(shù)定義為內(nèi)聯(lián)函數(shù)inlinedoubleShow1(doubledX) { returndX*dX;}6.1內(nèi)聯(lián)函數(shù)的使用2024/8/125//2、在類聲明體內(nèi)實現(xiàn)的函數(shù)不用inline關(guān)鍵字,自動是內(nèi)聯(lián)函數(shù)。 doubleShow2(doubledX)const
{ returndX*dX; }6.1內(nèi)聯(lián)函數(shù)的使用2024/8/126//3、在函數(shù)聲明處可加可不加inline關(guān)鍵字。
doubleShow3(doubledX)const; //4、但在實現(xiàn)處必須加inline關(guān)鍵字inlinedoubleCPerson::Show3(doubledX)const{ returndX*dX;}6.1內(nèi)聯(lián)函數(shù)的使用2024/8/127內(nèi)聯(lián)函數(shù)使用時注意以下幾點。1、在內(nèi)聯(lián)函數(shù)中不允許用循環(huán)語句、開關(guān)語句和遞歸調(diào)用語句等。2、內(nèi)聯(lián)函數(shù)的定義必須出現(xiàn)在第一次調(diào)用內(nèi)聯(lián)函數(shù)之前。3、在類內(nèi)部定義并實現(xiàn)的成員函數(shù)自動是內(nèi)聯(lián)函數(shù),但在類內(nèi)定義成員函數(shù)時,如果使用了for()、while()、do{}while()、switch()等語句,該成員函數(shù)會自動轉(zhuǎn)為非內(nèi)聯(lián)函數(shù)。4、內(nèi)聯(lián)函數(shù)中不能夠有靜態(tài)數(shù)據(jù)。5、內(nèi)聯(lián)函數(shù)中不能夠有數(shù)組說明。6.1內(nèi)聯(lián)函數(shù)的使用2024/8/1286.1.3內(nèi)聯(lián)和非內(nèi)聯(lián)函數(shù)的選擇使用內(nèi)聯(lián)函數(shù)時間開銷的減少,以空間的消耗為代價,而且執(zhí)行效率的提高也不是絕對的。在決定使用內(nèi)聯(lián)函數(shù)時要進(jìn)行適當(dāng)?shù)娜∩?。不是所有的函?shù)都適合采用內(nèi)聯(lián)函數(shù)。構(gòu)造函數(shù)和析構(gòu)函數(shù)常常就不適合內(nèi)聯(lián),這是因為構(gòu)造函數(shù)和析構(gòu)函數(shù)在編譯時,往往會被編譯器附加一大堆代碼。全部內(nèi)聯(lián)可以嗎?6.1內(nèi)聯(lián)函數(shù)的使用2024/8/129看看CStudent類的構(gòu)造函數(shù):例6_2:構(gòu)造函數(shù)、析構(gòu)函數(shù)往往不適合作內(nèi)聯(lián)函數(shù)。smain6_2.cpp
構(gòu)造函數(shù)、析構(gòu)函數(shù)最好不要內(nèi)聯(lián)。6.1內(nèi)聯(lián)函數(shù)的使用2024/8/1210CStudent()構(gòu)造函數(shù)看起來是空的,但它可能含有相當(dāng)多的代碼(與編譯器的設(shè)計有關(guān))。CStudent的構(gòu)造函數(shù),需要構(gòu)建4000字節(jié)的空間,并且還需要按照基類的要求初始化這些空間,因此它包含了一個復(fù)雜的創(chuàng)建過程。構(gòu)造函數(shù)和析構(gòu)函數(shù)最好都在類內(nèi)聲明,類外實現(xiàn)。一般來說,實際編程時最好是不要內(nèi)聯(lián)任何函數(shù),除非函數(shù)確實很小很簡單。不要內(nèi)聯(lián)任何函數(shù)6.1內(nèi)聯(lián)函數(shù)的使用2024/8/12116.2const的使用const意味著分配了一塊不可改變的內(nèi)存。用const定義或說明常類型量時必須初始化。常類型量,也就是常量。const更重要的用途則在于說明函數(shù)參數(shù)以及函數(shù)返回類型。函數(shù)參數(shù)2024/8/1212const主要有以下幾種用法:1、const說明值常量。2、const說明指針。3、const說明函數(shù)參數(shù)及其返回值。4、const說明類中的常量和成員函數(shù)。6.2const的使用2024/8/12136.2.1const說明值常量1、說明符號常量,表明符號代表的是一個常量,說明格式如下:doubleconstPI=12;constdoublePI=12;2、說明數(shù)組常量,說明格式如下:const
int
I_ARRAY[]={3,2,1};3、說明對象常量,說明格式如下:constCInline1
oC1,oC2;在一排逗號隔開的變量中,只需要一個const就行了在前、在后定義都可以。6.2const的使用2024/8/1214const與C語言"#define"的差別:#definePI3.14無參宏不是符號常量,它沒有數(shù)據(jù)類型,沒有值,在內(nèi)存中不分配地址。它是在預(yù)處理時作宏替換,不作類型檢查。而const定義的常量是符號常量,有數(shù)據(jù)類型,有值,且其值不可改變,在內(nèi)存中有地址,編譯時要作類型檢查。6.2const的使用2024/8/12156.2.2const與指針指針涉及三個東西:一個是指針變量本身;另一個是指針——指針變量中所存放的值;再一個就是指針?biāo)赶虻膶ο蟆?.2const的使用2024/8/1216指針其實就是地址,它代表的是指針變量中存放的地址值;而指針變量是指用來存放指針的一個變量,它用來存放地址;注意:指針變量本身也有地址,有存儲單元;指針?biāo)赶虻膶ο笫侵改瞧臻g所“存放的東西”。指針變量本身的地址,與指針變量所指向的對象的存儲地址是兩個不同的地址。6.2const的使用2024/8/12176.2const的使用2024/8/1218const和指針變量的典型組合有以下三種情況:1、指向常量的指針
const
int
*p;2、常指針char*constpc="a";3、指向常量的常指針constchar*constpc="a";6.2const的使用2024/8/1219
const
int*p;char*constpc="a";
constchar*constpc="a";畫一條垂直線穿過指針聲明中的星號(*)位置。如果const出現(xiàn)在線的左邊,則指針指向的對象為常量;如果const出現(xiàn)在線的右邊,則指針本身為常量;如果const在線的兩邊都出現(xiàn),則二者都是常量,是指向常量的常指針。6.2const的使用2024/8/12201指向常量的指針指針指向一個不可改變的量。指向常量。在聲明時可以不初始化。該指針可以指向這個常量,也可以指向另一個常量。指針變量里的指針值是可以改變的;但某一個具體指針值(即:某個指針)所指向的那個對象則是不可以改變的。對象不可改變。6.2const的使用2024/8/1221它也可以指向變量;從指針角度而言,所指向的是一個常量,通過該指針不能修改它所指向的對象;該指針變量可以存放常量地址也可以存放變量地址。對象不可改變。6.2const的使用2024/8/1222constchar*pc="ABCD";
pc[3]='a'; //不可以。pc=“EFGH”; //可以//step是一個指向常量的指針數(shù)組constchar*step[3]={"left","right","top"};step[2]="skip"; //可以。step[2][1]='i'; //不可以。6.2const的使用2024/8/12232常指針
<類型>*const<指針名>[=<初值>;]指針變量里面存放的是個常量,稱為常指針,指針變量里面裝的是一個固定值,在定義時必須初始化。常指針一旦初始化后,不能夠再指向其他內(nèi)存單元。通過常指針可以修改它所指向的內(nèi)存單元的內(nèi)容,也就是修改常指針?biāo)赶虻膶ο蟆?.2const的使用2024/8/1224char*constpc="ABCD"; //常指針pc[3]='a'; //可以。pc="EFGH"; //不可以//step是一個常指針數(shù)組char*conststep[3]={"left","right","top"};step[2]="skip"; //不可以。step[2][1]='i'; //可以。6.2const的使用2024/8/12253指向常量的常指針指針本身及指針?biāo)赶虻膶ο蠖疾豢筛淖?。二者都要聲明為const。在聲明時必須初始化。指針本身及其指向的對象均不能改變。constchar*constpc="asdf";
pc[3]='a'; //不可以。pc="ABCD"; //不可以。6.2const的使用2024/8/12266.2.3const說明函數(shù)參數(shù)和返回值是const最重要的應(yīng)用。在值傳遞場合不必用const。用const去修飾用指針和引用傳遞的函數(shù)參數(shù),是安全的。const修飾函數(shù)的返回值。安全的6.2const的使用2024/8/1227voidFunc(constchar
*lpszChar);voidFunc(charconst
*lpszChar);//以上二者等價。//參數(shù)是對象的常引用,返回值也是一個對象的常引用。constCStudent
&Func(const
CStudent
&oCStudent); 對返回值使用const也有可能提高函數(shù)的安全性和效率。6.2const的使用2024/8/12286.2.4類中的const在類中,const的使用也比較廣。它可以用于修飾類中的成員函數(shù)和成員數(shù)據(jù)。主要應(yīng)用6.2const的使用2024/8/12291常成員函數(shù)不可以改變對象數(shù)據(jù)成員的函數(shù)。在一般成員函數(shù)后面加上const即可。1、用const關(guān)鍵詞修飾一個成員函數(shù),說明該成員函數(shù)是“只讀”的。2、只有常成員函數(shù)可以操作常對象,常對象只能調(diào)用常成員函數(shù)(const成員函數(shù))。3、一般對象不但可以調(diào)用一般成員函數(shù),也可以調(diào)用常成員函數(shù)。6.2const的使用2024/8/1230例6_3:常對象只能夠調(diào)用常成員函數(shù),不能夠調(diào)用一般成員函數(shù),而一般對象可以調(diào)用所有的成員函數(shù)。s6_3\sclass6_3_T.hs6_3\sclass6_3_point.cpps6_3\smain6_3.cpp運行結(jié)果一般成員函數(shù)調(diào)用:12一般成員函數(shù)調(diào)用:23
常成員函數(shù)調(diào)用:33
6.2const的使用2024/8/1231例子表明:僅在const方面有不同的成員函數(shù)是可以重載的,編譯器能夠正確區(qū)分這兩個函數(shù)。而對調(diào)用對象來說,一般對象優(yōu)先調(diào)用重載的一般函數(shù),其次才是const函數(shù);常對象(const對象)則只能夠調(diào)用const函數(shù),不能夠調(diào)用一般函數(shù)。對于一般對象,當(dāng)調(diào)用一般成員函數(shù)不成功時,系統(tǒng)自動會轉(zhuǎn)入對常成員函數(shù)的調(diào)用。6.2const的使用2024/8/12322常數(shù)據(jù)成員若一個數(shù)據(jù)成員的前面用了關(guān)鍵詞const修飾符,則該數(shù)據(jù)成員為常數(shù)據(jù)成員。const型的數(shù)據(jù)必須初始化,且不能修改,它是常數(shù)據(jù)成員。常數(shù)據(jù)成員的初始化方式——在定義對象時,通過在構(gòu)造函數(shù)后面加上成員初始化列表來完成的。smain6_4.cpp
6.2const的使用2024/8/1233classCPoint //CPoint類{private:
intm_x; //x坐標(biāo)
constintm_y; //y坐標(biāo),常數(shù)據(jù)成員
staticconstintm_z; //z坐標(biāo),靜態(tài)常數(shù)據(jù)成員};constint
CPoint::m_z=0; //靜態(tài)數(shù)據(jù)成員的初始化方式。//構(gòu)造函數(shù),m_y采用了初始化表的方式初始化。CPoint::CPoint(intx,inty):m_y(y)
{
m_x=x; //正確。
//m_y=y; //錯。}6.2const的使用2024/8/1234在CPoint中設(shè)置了空間坐標(biāo)中的m_x、m_y和m_z坐標(biāo)。分別把它們設(shè)置成一般數(shù)據(jù)成員、常數(shù)據(jù)成員和靜態(tài)常數(shù)據(jù)成員。由于類型不同,它們所采用的初始化方式是很不一樣的。在設(shè)計構(gòu)造函數(shù)時,最好對一般成員數(shù)據(jù)也采用初始化表的方式進(jìn)行初始化。這樣效率最高。6.2const的使用2024/8/12353常對象常對象就是其值不可改變的對象。它是只可以取值不可以修改的對象。常對象一旦建立并初始化以后,只可以通過常成員函數(shù)來訪問它。constCPointocCPoint3(3,3);
6.2const的使用2024/8/12366.3動態(tài)內(nèi)存管理技術(shù)動態(tài)對象就是程序在運行過程中在動態(tài)內(nèi)存中建立的對象。這類對象需要用戶自己使用new運算符創(chuàng)建,使用delete運算符釋放,需要用戶自己管理。堆棧靜態(tài)內(nèi)存2024/8/12376.3.1內(nèi)存的幾種分配方式計算機(jī)內(nèi)存通常具有三種組織方式:堆、棧和靜態(tài)內(nèi)存。1、在靜態(tài)存儲區(qū)中分配。靜態(tài)存儲區(qū)中的變量空間在編譯時分配。靜態(tài)內(nèi)存區(qū)中的變量在程序的整個運行期間都存在。其生命周期貫穿整個程序的運行周期。例如全局變量,static變量等在這個區(qū)間分配。6.3動態(tài)內(nèi)存管理技術(shù)2024/8/12382、在棧上分配自動變量等局部變量在棧上分配存儲空間。函數(shù)內(nèi)的局部變量在棧上分配存儲單元。它的生命周期與函數(shù)的執(zhí)行時間相同。當(dāng)函數(shù)執(zhí)行結(jié)束時這些存儲單元會被自動釋放,其生命周期也就完結(jié)了。6.3動態(tài)內(nèi)存管理技術(shù)2024/8/12393、在堆上分配,亦稱動態(tài)內(nèi)存分配。動態(tài)內(nèi)存由程序員自己負(fù)責(zé)管理。運行時用new申請內(nèi)存。程序員負(fù)責(zé)在不需要時用delete釋放內(nèi)存。比拉登還麻煩。容易出問題。6.3動態(tài)內(nèi)存管理技術(shù)2024/8/12406.3.2使用new和delete分配和釋放動態(tài)內(nèi)存malloc()與free()標(biāo)準(zhǔn)庫函數(shù);new/delete運算符(不是庫函數(shù))。malloc()/free()功能有限。用戶自定義類型在創(chuàng)建對象時要執(zhí)行構(gòu)造函數(shù),對象在消亡之前要執(zhí)行析構(gòu)函數(shù)。而且是自動執(zhí)行的。所以,C++使用能完成動態(tài)內(nèi)存分配和初始化工作的運算符new,及能完成清理與釋放內(nèi)存工作的運算符delete來管理動態(tài)內(nèi)存。6.3動態(tài)內(nèi)存管理技術(shù)2024/8/12416.3.2.1new運算符
new用來動態(tài)地分配存儲空間。它能夠自動計算要分配的存儲空間大小并能返回正確的指針類型。若返回值為NULL,則表示動態(tài)內(nèi)存分配不成功。在用new申請動態(tài)內(nèi)存后,一定要判斷動態(tài)內(nèi)存是否分配成功。if(p!=NULL)6.3動態(tài)內(nèi)存管理技術(shù)2024/8/1242int*pInt1,*pInt2;pInt1=newint; //new運算返回一整數(shù)單元的地址pInt2=newint(200); //new一個int單元,并將其初始化為200。int*pInt3,(*pInt4)[3];
pInt3=newint[10];//new運算返回一整數(shù)單元的地址,有10個這樣的單元。pInt4=newint[2][3]; //new運算返回每行為3個元素的行地址CPoint
*poCPoint;poCPoint=newCPoint(10,10); //new運算返回對象的地址,并在動態(tài)內(nèi)存中創(chuàng)建了一個對象。6.3動態(tài)內(nèi)存管理技術(shù)2024/8/1243使用new運算符創(chuàng)建數(shù)組時,不能為該數(shù)組指定初值。執(zhí)行“CPoint
poCPoint=newCPoint(10,10);”語句時,得到了兩個東西:一個是對象指針變量,另一個是在動態(tài)內(nèi)存空間中的對象,而指針變量中的值,就是這個動態(tài)內(nèi)存空間中的對象的首地址,也就是動態(tài)內(nèi)存地址。而且這個對象是沒有名字的,只有通過指針進(jìn)行訪問。6.3動態(tài)內(nèi)存管理技術(shù)2024/8/12442delete運算符delete釋放new所分配的存儲空間。<指針名>是存放了要釋放的存儲空間地址的指針變量名字。釋放new所創(chuàng)建數(shù)組時,使用“delete[]<指針名>;”的形式。delete只能用來釋放用new申請得的動態(tài)內(nèi)存空間,而且一次new只能夠?qū)?yīng)一次delete。配對使用6.3動態(tài)內(nèi)存管理技術(shù)2024/8/1245deletepInt1;deletepInt2;delete[]pInt3;//釋放用new申請的數(shù)組空間//釋放由new申請的數(shù)組空間,對多維空間的釋放格式與一維空間相同。delete[]pInt4; deletepoCPoint;//釋放一個對象6.3動態(tài)內(nèi)存管理技術(shù)2024/8/1246注意:delete后,指針?biāo)赶虻膬?nèi)存空間就釋放了,但指針變量的值并沒有改變。指針還指向原來的內(nèi)存空間。所以,delete以后,應(yīng)將指針變量的值設(shè)置成NULL,讓它不再指向原來的內(nèi)存空間,以免誤操作。例6_5:顯示了new和delete的基本使用smain6_5.cpp6.3動態(tài)內(nèi)存管理技術(shù)2024/8/1247
CPoint
*poCPoint; //創(chuàng)建對象時,自動調(diào)用構(gòu)造函數(shù)。
poCPoint=newCPoint[ARRAY_SIZE];//判斷動態(tài)內(nèi)存申請是否成功。
if(poCPoint==NULL) {
cout<<"動態(tài)內(nèi)存分配失敗。\n"; exit(0);//內(nèi)存申請失敗,則退出. }6.3動態(tài)內(nèi)存管理技術(shù)2024/8/1248
delete[]poCPoint; //釋放對象數(shù)組。
//動態(tài)內(nèi)存釋放后,讓poCPoint指針指向NULL。否則,它依然指向原動態(tài)空間。
poCPoint=NULL;
其內(nèi)容為垃圾6.3動態(tài)內(nèi)存管理技術(shù)2024/8/1249在例6_5中,數(shù)組中的5個對象其坐標(biāo)都是(0,0,0)。這是由于給數(shù)組分配空間時,不能進(jìn)行初始化(聲明時不能夠帶參數(shù))。也就是說:new一個對象數(shù)組時是不能夠帶參數(shù)的。缺省的參數(shù)則可以,構(gòu)造函數(shù)缺省值為(0,0,0)。6.3動態(tài)內(nèi)存管理技術(shù)2024/8/1250對象數(shù)組的對象初始化有兩種方法:1、在類中不定義構(gòu)造函數(shù),而定義一個成員函數(shù)專門用來完成初始化。2、在所定義的類中增加不帶參數(shù)或帶缺省參數(shù)的構(gòu)造函數(shù)。6.3動態(tài)內(nèi)存管理技術(shù)2024/8/1251"poCPoint=newCPoint[ARRAY_SIZE];“表明對應(yīng)著: "delete[]poCPoint;";
而:"CTemp
*poCTemp=newCTemp(5);” 對應(yīng)著: "deletepoCTemp;"。如果new和delete形式不對應(yīng),結(jié)果將不可預(yù)測。6.3動態(tài)內(nèi)存管理技術(shù)2024/8/12523new和delete的重載
new和delete可以在類內(nèi)重載,也可以在類外重載。類外重載就是全局函數(shù)重載,它會覆蓋系統(tǒng)預(yù)定義的new和delete功能,。類內(nèi):new和delete只能重載為成員函數(shù),不能重載為友元函數(shù)。而且,無論是否使用關(guān)鍵字static進(jìn)行修飾,重載了的new和delete均為類的靜態(tài)成員函數(shù)。6.3動態(tài)內(nèi)存管理技術(shù)2024/8/1253void*operatornew(size_tsize){void*p=malloc(size);return(p);}voidoperatordelete(void*p);{free(p);}6.3動態(tài)內(nèi)存管理技術(shù)2024/8/12546.3.3常見的動態(tài)內(nèi)存錯誤編譯器不能自動發(fā)現(xiàn)動態(tài)內(nèi)存錯誤。在程序運行時才能捕捉到。常見的動態(tài)內(nèi)存錯誤有:1、使用未分配成功的動態(tài)內(nèi)存空間。在使用動態(tài)內(nèi)存之前必須檢查指針是否為NULL:函數(shù)入口處:assert(p!=NULL)
assert()函數(shù)對應(yīng)的頭文件為:assert.h參考《C語言程序設(shè)計(C99)》,清華大學(xué)出版社申請時用:if(p==NULL)或if(p!=NULL)
進(jìn)行檢查.6.3動態(tài)內(nèi)存管理技術(shù)2024/8/12552、使用未經(jīng)初始化的動態(tài)內(nèi)存空間。內(nèi)存的缺省初值可能是一個不確定的值
,所以,任何內(nèi)存空間的使用都應(yīng)該立足于自己初始化。盡量不要使用系統(tǒng)缺省的初值。3、超過了內(nèi)存空間的邊界使用指針指向了不正確的類型時,會出錯;數(shù)組的操作也很容易越界;越界后就會操作到不正確的內(nèi)存單元.6.3動態(tài)內(nèi)存管理技術(shù)2024/8/12564、內(nèi)存泄露。是一種嚴(yán)重的內(nèi)存錯誤,極不容易發(fā)現(xiàn)。程序長期運行的話,最終會導(dǎo)致內(nèi)存耗盡。由于new和delete使用不配對new創(chuàng)建的動態(tài)空間,沒有用delete釋放等。5、使用已經(jīng)釋放了的內(nèi)存空間。用free或delete釋放內(nèi)存以后,指針變量p的值并沒有改變,它依然指向原來new的那一片內(nèi)存空間。釋放內(nèi)存以后,一定要將指針變量的值置成NULL。另外,在傳遞內(nèi)存指針時要避免傳遞棧內(nèi)存(存儲臨時變量的內(nèi)存)。6.3動態(tài)內(nèi)存管理技術(shù)2024/8/12576.3.4指針和數(shù)組的對比數(shù)組名對應(yīng)著一塊內(nèi)存,其地址與容量在生命期內(nèi)保持不變,數(shù)組的內(nèi)容則可以改變;指針變量(尤其void*)則是一個變量,它可以存放任意的地址值,它可以隨時指向任意類型的內(nèi)存塊,所以指針遠(yuǎn)比數(shù)組靈活、危險。例6_7說明了指針和數(shù)組在使用上的一些差異。使用不慎將引發(fā)內(nèi)存問題。smain6_7.cpp6.3動態(tài)內(nèi)存管理技術(shù)Oelloworldhellohello1242024/8/12586.3.5利用指針傳遞內(nèi)存的方式利用函數(shù)申請動態(tài)內(nèi)存,可以使用指向指針的指針、指針引用以及函數(shù)返回指針來傳遞動態(tài)內(nèi)存。例6_8:利用指向指針的指針、指針引用和函數(shù)返回指針傳遞內(nèi)存。smain6_8.cpphello,world.hello,china.hello,四川大學(xué)計算機(jī)學(xué)院!6.3動態(tài)內(nèi)存管理技術(shù)2024/8/1259例6_9:利用指針傳遞內(nèi)存時,注意不要傳遞棧內(nèi)存,否則指針會指向垃圾。smain6_9.cpp
棧內(nèi)存調(diào)用的結(jié)果為:,_x0012_靜態(tài)內(nèi)存調(diào)用的結(jié)果為:helloworld在例6_9中:GetString1的return語句返回了指向“棧內(nèi)存”的指針,它是錯誤的,因為該內(nèi)存在函數(shù)結(jié)束時自動消失;而GetString2雖然返回了正確的結(jié)果,但它在設(shè)計概念上就已經(jīng)錯誤了(因得到的是常量空間)。6.3動態(tài)內(nèi)存管理技術(shù)2024/8/1260以下兩者本質(zhì)上是不同的:charaChar[]="helloworld"; char*aChar="helloworld";動態(tài)數(shù)組初始化6.3動態(tài)內(nèi)存管理技術(shù)2024/8/12616.3.6delete的作用delete只是把指針?biāo)赶虻膬?nèi)存給釋放掉,它并沒有使指針本身消失。delete以后,指針還是指向其原來指向的內(nèi)存空間,指針變量的值并未改變。指針?biāo)赶虻膬?nèi)存空間的內(nèi)容已經(jīng)釋放掉了,其內(nèi)容變得毫無意義了,是垃圾,指針本身被懸掛了。此時用語句if(p!=NULL)進(jìn)行防錯處理是毫無意義的.6.3動態(tài)內(nèi)存管理技術(shù)2024/8/1262在例6_10中,安排了這種懸掛所帶來的問題的示例程序。例6_10:delete對內(nèi)存干了什么?smain6_10.cpp
lpszChar和lpszChar2指向了同一片動態(tài)內(nèi)存空間,delete以后,內(nèi)存的內(nèi)容毫無意義,但是lpszChar和lpszChar2指針變量的值并沒有改變,還指向原來的位置。6.3動態(tài)內(nèi)存管理技術(shù)2024/8/1263lpszChar2:屯屯屯屯屯屯屯屯葺葺葺葺葺葺lpszChar:屯屯屯屯屯屯屯屯葺葺葺葺葺葺lpszChar2:hello,China!lpszChar:hello,China!lpszChar2:葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺lpszChar:葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺lpszChar2:helloworld。lpszChar:helloworld。6.3動態(tài)內(nèi)存管理技術(shù)2024/8/1264預(yù)防“指針懸掛”和“野指針”(此處“指針懸掛”和“野指針”是同義詞,都指指針指向不可用內(nèi)存區(qū)域)從以下幾點入手:1、聲明指針時記住初始化,如不初始化就一定將其置成NULL.2、指針delete以后,一定記得將其置為NULL。3、當(dāng)指針指向數(shù)組時,謹(jǐn)防指針操作越界.4、避免指針指向一個已經(jīng)自動消失的局部變量。6.3動態(tài)內(nèi)存管理技術(shù)2024/8/1265voidFunc(void){ char*lpszChar=newchar[100]; }//在退出函數(shù)時,動態(tài)內(nèi)存會自動釋放嗎?6.3動態(tài)內(nèi)存管理技術(shù)2024/8/1266退出Func()的時候,lpszChar會自動消失;而動態(tài)內(nèi)存卻依然存在,沒有釋放,造成內(nèi)存泄漏。1、指針消亡了,并不表示它所指向的動態(tài)內(nèi)存會自動釋放了。2、動態(tài)內(nèi)存釋放了,并不表示指向該動態(tài)內(nèi)存的指針會消亡或自動變成NULL指針。6.3動態(tài)內(nèi)存管理技術(shù)2024/8/12676.4使用引用引用(&),就是給一個變量取別名。使用“引用”就是使用“被引用對象”本身它不需要建立臨時對象,傳遞效率較高。6.4.1引用類型intiA,iB;int&riA=iA;//int&riA=iB;//錯誤,引用是固定的。riA是iA的同義詞,它們表示同一個對象。2024/8/1268riA是iA的一個引用;iA是一般變量,它是被引用的對象。定義引用類型變量時必須初始化。引用只能引用一個固定的對象。初始化以后,引用關(guān)系就不可改變。對對象或?qū)σ玫娜魏尾僮鞫紩绊懙奖灰脤ο蟊旧?。一個引用可看作一個特殊類型的指針。6.4使用引用2024/8/12691指針引用C中,改變指針本身——采用傳指針地址的方式.voidFunc(int
**ppInt);int
iNum=47;int
*pInt=&iNum; //&表示取一般變量的地址Func(&pInt); //&表示取指針變量的地址6.4使用引用2024/8/1270利用指針引用傳遞"指針值"。C++中,可以采用引用來完成。函數(shù)參數(shù)變成指針的引用,用不著取得指針的地址。voidNewMemory3(char*&lpszChar,int
iNum){
lpszChar=newchar[iNum]; if(NULL==lpszChar)
{
cout<<"內(nèi)存分配失敗"<<endl; exit(0); }}6.4使用引用2024/8/1271voidTest3(void){ char*lpszStr=NULL;
NewMemory3(lpszStr,100);
strcpy(lpszStr,"hello,world.");
cout<<lpszStr<<endl; deletelpszStr;}傳遞動態(tài)內(nèi)存(用戶定義函數(shù))6.4使用引用2024/8/12726.4.1.2使用引用的限制使用引用時注意兩點:1、引用必須初始化。2、引用在初始化中被綁定到某個對象上后,將只能永遠(yuǎn)綁定這個對象。不可空引用6.4使用引用2024/8/1273引用的效能:1、引用主要用于函數(shù)參數(shù)傳遞,解決大塊數(shù)據(jù)或?qū)ο蟮膫鬟f效率和空間效率問題。2、用引用傳遞函數(shù)參數(shù),不產(chǎn)生副本,提高傳遞效率,通過const的使用,保證了引用傳遞的安全性。3、引用與指針的區(qū)別:指針通過某個指針變量指向一個對象后,對它所指向的變量間接操作。指針使程序可讀性差;而引用本身就是目標(biāo)變量的別名,對引用的操作就是對目標(biāo)變量的操作。引用固定,安全性高;指針可指向任何位置,危險。4、使用引用的時機(jī):重載流操作符<<和>>的參數(shù)、賦值操作符=的返回值、拷貝構(gòu)造函數(shù)的參數(shù)、賦值操作符=的參數(shù)、以及其它部分情況下都推薦使用引用。6.4使用引用2024/8/12746.4.2獨立引用1、初始化時,賦值表達(dá)式的右端是一個變量。例如:int
&riNum=iNum;iNum是一個變量。2、初始化時,賦值表達(dá)式的右端是一個常量值。例如(VC不允許對常量的引用)constdouble&rd2=1.0;實際上,相當(dāng)于:constdoublerd2=1.0;6.4使用引用2024/8/1275例6_11:引用變量和被引用變量的值同步變化.smain6_11.cpp
5006006005006006006.4使用引用2024/8/12766.4.3引用作為函數(shù)參數(shù)值傳遞只能實現(xiàn)實參到形參的傳值,不能實現(xiàn)形參到實參的反向傳值。C++中,需要雙向傳值時,還可以采用引用。使用引用比使用指針傳值更安全,更方便,更直觀,更容易理解。例6_12:引用作為參數(shù),產(chǎn)生了雙向傳值的效果。smain6_12.cpp6.4使用引用2024/8/1277提高傳值的效率:
采用引用傳值,可以避免復(fù)制傳值過程,相應(yīng)地提高了傳值的效率。引用就是實參對象本身,不需要復(fù)制。如果采用常引用,也不會改變實參,對實參來說也是安全的。例6_13:常引用作參數(shù),在不需要修改實參的時候,保證了所傳遞參數(shù)的安全性。而且傳遞效率高。smain6_13.cpp
6.4使用引用2024/8/12786.4.4引用返回值
函數(shù)返回引用,返回的是一個存儲單元(即變量)。因此,如果一個函數(shù)返回引用的話,則函數(shù)調(diào)用可以出現(xiàn)在賦值號的右邊。也可以出現(xiàn)在賦值號的左邊。例6_14:引用作為返回值。smain6_14.cpp6.4使用引用2024/8/1279函數(shù)返回引用作為左值使用的結(jié)果。在函數(shù)中未對數(shù)組元素作任何修改,但是數(shù)組元素值卻改變了。這是函數(shù)返回引用,并被作為左值操作的結(jié)果。
10010200102,4,6,8,10,12,14,16,18,20,2,4,6,8,10,12,100,16,18,20,6.4使用引用2024/8/12806.4.5常引用常引用是用const修飾的引用,它常常用做形式參數(shù),用來限制對實參對象的修改。例如://參數(shù)是常引用,在函數(shù)中不可改變它。voidFunc(constCStudent
&oCStudent); //不可通過riNum改變iNum的值。constint
&riNum=iNum;
6.4使用引用2024/8/1281例6_15:從源復(fù)制指定大小的字節(jié)數(shù)到目的。smain6_15.cpp程序中,使用了“constvoid*pvFrom”作為形式參數(shù),這保證了實際參數(shù)lpszSource的安全性。同時也不會采用復(fù)制傳值,直接使用lpszSource,傳遞效率最高。6.4使用引用2024/8/12826.5類型轉(zhuǎn)換類型轉(zhuǎn)換就是將一種類型轉(zhuǎn)換為另一種類型:標(biāo)準(zhǔn)類型之間可以相互轉(zhuǎn)換。類類型之間,標(biāo)準(zhǔn)類型和類類型之間也可以相互轉(zhuǎn)換。對于標(biāo)準(zhǔn)類型來說,C++提供了隱式類型轉(zhuǎn)換和顯示類型轉(zhuǎn)換兩種機(jī)制。而自定義類類型到基本類型的轉(zhuǎn)換則可由自己定義的構(gòu)造函數(shù)和類型轉(zhuǎn)換函數(shù)來實現(xiàn)。2024/8/12836.5.1構(gòu)造函數(shù)和類型轉(zhuǎn)換函數(shù)利用構(gòu)造函數(shù)只能完成基本類型到類類型的轉(zhuǎn)換。從類類型到基本類型的轉(zhuǎn)換需要定義類型轉(zhuǎn)換函數(shù)。1基本類型轉(zhuǎn)化為類類型用構(gòu)造函數(shù)進(jìn)行類型轉(zhuǎn)換有一個前提,就是類中有一個只帶一個參數(shù)的構(gòu)造函數(shù)。例6_16:實現(xiàn)由實型數(shù),字符串到CDouble類型的轉(zhuǎn)換。smain6_16.cpp6.5類型轉(zhuǎn)換2024/8/1284構(gòu)造函數(shù)(1)完成從double型到CDouble類類型的轉(zhuǎn)換;構(gòu)造函數(shù)(2)完成從char*到CDouble類類型的轉(zhuǎn)換,雖然它有2個參數(shù),但第2個參數(shù)缺省,所以它也可以只帶一個參數(shù)轉(zhuǎn)換。6.5類型轉(zhuǎn)換2024/8/12856.5.1.2類類型轉(zhuǎn)化為基本類型完成類類型到基本類型的轉(zhuǎn)換,可采用類類型轉(zhuǎn)換函數(shù)來實現(xiàn)。類類型轉(zhuǎn)換函數(shù)專門用來將類類型轉(zhuǎn)換為基本數(shù)據(jù)類型。
operator<基本類型名>(){ //…… return<基本類型值>;}無返回類型6.5類型轉(zhuǎn)換2024/8/1286沒有返回類型,<類型名>就代表了它的返回類型;沒有任何參數(shù)。在調(diào)用過程中要帶一個對象實參。類類型轉(zhuǎn)換函數(shù)沒有返回類型說明,但函數(shù)體必須有return語句,用于返回<基本類型值>。
例6_17的"operatorint();"定義了一個類類型轉(zhuǎn)換為基本類型的例子。smain6_17.cpp6.5類型轉(zhuǎn)換2024/8/1287CInteger::operatorint(){ returnm_iNum;}定義類類型轉(zhuǎn)換函數(shù)時,應(yīng)注意下列幾點:1、轉(zhuǎn)換函數(shù)是類的非靜態(tài)成員函數(shù)。2、轉(zhuǎn)換函數(shù)定義時,不進(jìn)行返回值的類型說明,也沒有形參。6.5類型轉(zhuǎn)換2024/8/12886.5.2一個類型轉(zhuǎn)換實例例6_18:直角坐標(biāo)到極(矢量)坐標(biāo)的相互轉(zhuǎn)換。smain6_18.cpp
6.5類型轉(zhuǎn)換X坐標(biāo)為:2;Y坐標(biāo)為:2X坐標(biāo)為:0;Y坐標(biāo)為:0極徑=4;極角=0.523333弧度。極徑=0;極角=0弧度。X坐標(biāo)為:2;Y坐標(biāo)為:2X坐標(biāo)為:3.46463;Y坐標(biāo)為:1.99908極徑=4;極角=0.523333弧度。極徑=2.82843;極角=0.785398弧度。2024/8/12896.6異常處理出錯處理即異常處理是提高程序健壯性的重要手段。異常主要指程序運行時異常。異常處理機(jī)制就是用于管理這種異常的一種方法。異常處理的基本結(jié)構(gòu)throw、try和catch語句的一般語法如下:2024/8/1290throw<表達(dá)式>;try
{//try語句塊}catch(類型1參數(shù)1){//針對類型1的異常處理}catch(類型2參數(shù)2){//針對類型2的異常處理}//…
catch(類型n參數(shù)n){//針對類型n的異常處理}1個參數(shù)6.6異常處理2024/8/1291在設(shè)計catch程序時,catch出現(xiàn)的順序很重要。在一個try塊中引發(fā)異常時,異常處理程序按照它在catch中出現(xiàn)的順序進(jìn)行檢查。catch的排列順序應(yīng)從特殊到一般的排列順序(指異常對象從特殊到一般排列)。即應(yīng)該將派生的異常捕獲放在前面,而將基類異常對象的捕獲放在處理程序后面。6.6異常處理2024/8/12926.6.1C語言的出錯處理C語言的出錯處理方法,無法正確地清除對象。C++語言異常處理將異常的檢測與處理分開。C++異常處理機(jī)制采用結(jié)構(gòu)化方法,就是:throw、try、catch結(jié)構(gòu)。
1、throw:用來創(chuàng)建用戶自定義類型的異常錯誤,用于拋出異常。2、try:標(biāo)識程序中異常語句塊,用于引發(fā)異常。3、catch:標(biāo)識異常錯誤處理模塊,用于捕獲、處理異常。6.6異常處理2024/8/12936.6.2拋出異常throw<表達(dá)式>;
使用一般方式if(條件)throw<表達(dá)式>異常規(guī)格申明(下個頁面還將詳細(xì)介紹)比如:voidExceptionFunction(argument)throw(ExceptionClass1,ExceptionClass2)表示函數(shù)ExceptionFunction中可拋出ExceptionClass1或ExceptionClass2類型的異常.如果某段程序發(fā)現(xiàn)了自己不能處理的異常,就可以使用throw表達(dá)式拋出這個異常,將它拋給調(diào)用者。6.6異常處理2024/8/1294異常規(guī)格申明
溫馨提示
- 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 浙江農(nóng)林大學(xué)《體育統(tǒng)計學(xué)(含體育測量與評價)》2023-2024學(xué)年第二學(xué)期期末試卷
- 《歸去來兮辭》教學(xué)設(shè)計 2023-2024學(xué)年統(tǒng)編版高中語文選擇性必修下冊
- 天津理工大學(xué)中環(huán)信息學(xué)院《有毒有害物質(zhì)檢測》2023-2024學(xué)年第二學(xué)期期末試卷
- 中國美術(shù)學(xué)院《財務(wù)信息系統(tǒng)》2023-2024學(xué)年第二學(xué)期期末試卷
- 西藏警官高等??茖W(xué)?!度襟w新聞評論》2023-2024學(xué)年第二學(xué)期期末試卷
- 大連科技學(xué)院《工程項目管理A》2023-2024學(xué)年第二學(xué)期期末試卷
- 廣西工商職業(yè)技術(shù)學(xué)院《制藥分離工程》2023-2024學(xué)年第二學(xué)期期末試卷
- 重慶交通大學(xué)《會計信息系統(tǒng)(一)》2023-2024學(xué)年第二學(xué)期期末試卷
- 瀘州四川瀘州市國有土地上房屋征收補(bǔ)償中心(瀘州市物業(yè)管理中心)招聘編外人員筆試歷年參考題庫附帶答案詳解
- 泰州2025年江蘇泰州市第四人民醫(yī)院招聘合同制人員27人筆試歷年參考題庫附帶答案詳解
- 敬老院設(shè)備采購?fù)稑?biāo)方案(技術(shù)方案)
- 充電樁采購安裝售后服務(wù)方案
- 《旅行社條例》和《旅行社管理條例》對比解讀
- 柳宗元抑郁而堅貞的一生
- 鄉(xiāng)鎮(zhèn)人大代表選舉結(jié)果情況報告單
- BOPP雙向拉伸薄膜及膠帶生產(chǎn)項目環(huán)境影響報告
- 頻譜儀N9020A常用功能使用指南
- 天津高考英語詞匯3500
- 上海市2023年中考數(shù)學(xué)試卷(附答案)
- 《種太陽》公開課課件
- access上機(jī)練習(xí)題題庫
評論
0/150
提交評論