




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、C+關(guān)鍵字new學(xué)習(xí)很多新手對(duì)C+關(guān)鍵字new可能不是很了解吧,今天我一起來學(xué)習(xí)一下?!皀ew是C+的一個(gè)關(guān)鍵字,同時(shí)也是操作符。關(guān)于new的話題非常多,因?yàn)樗_實(shí)比較復(fù)雜,也非常神秘,下面我將把我了解到的與new有關(guān)的內(nèi)容做一個(gè)總結(jié)。new的過程classAinti;public:A(int_i):i(_i*_i)voidSay()printf(i=%dn,i);/調(diào)用new:A*pa=newA(3);A*pa=(A*)malloc(sizeof(A);pa-A:A(3);returnpa;到目前為止,本文所提到的new都是指的“newoperator或稱為newexpression,但事實(shí)
2、上在C+中一提到new,至少可能代表以下三種含義:newoperator、operatornew、placementnew。newoperator的第一步分配內(nèi)存實(shí)際上是通過調(diào)用operatornew來完成的,這里的new實(shí)際上是像加減乘除一樣的操作符,因此也是可以重載的。operatornew默認(rèn)情況下首先調(diào)用分配內(nèi)存的代碼,嘗試得到一段堆上的空間,如果成功就返回,如果失敗,則轉(zhuǎn)而去調(diào)用一個(gè)new_hander,然后繼續(xù)重復(fù)前面過程。如果我們對(duì)這個(gè)過程不滿意,就可以重載operatornew,來設(shè)置我們希望的行為。例如:這里通過:operatornew調(diào)用了原有的全局的new,實(shí)現(xiàn)了在分配內(nèi)
3、存之前輸出一句的。全局的operatornew也是可以重載的,但這樣一來就不能再遞歸的使用new來分配內(nèi)存,而只能使用malloc了:相應(yīng)的,delete也有deleteoperator和operatordelete之分,后者也是可以重載的。并且,如果重載了operatornew,就應(yīng)該也相應(yīng)的重載operatordelete,這是良好的編程習(xí)慣。#includevoidmain()charssizeof(A);A*p=(A*)s;new(p)A(3);/p-A:A(3);p-Say();p-A();正如前面所說,operatornew的默認(rèn)行為是請(qǐng)求分配內(nèi)存,如果成功則返回此內(nèi)存地址,如果失
4、敗則調(diào)用一個(gè)new_handler,然后再重復(fù)此過程。于是,想要從operatornew的執(zhí)行過程中返回,則必然需要滿足下列條件之一:分配內(nèi)存成功new_handler中拋出bad_alloc異常new_handler中調(diào)用exit()或類似的函數(shù),使程序結(jié)束void*operatornew(size_tsize)void*p=nullwhile(!(p=malloc(size)if(null=new_handler)throwbad_alloc();trynew_handler();catch(bad_alloce)throwe;catch()returnp;voidMyNewHandler
5、()printf(“Newhandlercalled!n”);throwstd:bad_alloc();std:set_new_handler(MyNewHandler);在編程時(shí)我們應(yīng)該注意到對(duì)new的調(diào)用是有可能有異常被拋出的,因此在new的代碼周圍應(yīng)該注意保持其事務(wù)性,即不能因?yàn)檎{(diào)用new失敗拋出異常來導(dǎo)致不正確的程序邏輯或數(shù)據(jù)結(jié)構(gòu)的出現(xiàn)。例如:靜態(tài)變量count用于記錄此類型生成的實(shí)例的個(gè)數(shù),在上述代碼中,如果因new分配內(nèi)存失敗而拋出異常,那么其實(shí)例個(gè)數(shù)并沒有增加,但count變量的值卻已經(jīng)多了一個(gè),從而數(shù)據(jù)結(jié)構(gòu)被破壞。正確的寫法是:這樣一來,如果new失敗則直接拋出異常,count
6、的值不會(huì)增加。類似的,在處理線程同步時(shí),也要注意類似的問題:此時(shí),如果new失敗,unlock將不會(huì)被執(zhí)行,于是不僅造成了一個(gè)指向不正確地址的指針p的存在,還將導(dǎo)致someMutex永遠(yuǎn)不會(huì)被解鎖。這種情況是要注意避免的。(參考:C+箴言:爭取異常安全的代碼)STL的內(nèi)存分配與traits技巧為了實(shí)現(xiàn)這種方式,STL使用了placementnew,通過在自己管理的內(nèi)存空間上使用placementnew來構(gòu)造對(duì)象,以達(dá)到原有newoperator所具有的功能。此函數(shù)接收一個(gè)已構(gòu)造的對(duì)象,通過拷貝構(gòu)造的方式在給定的內(nèi)存地址p上構(gòu)造一個(gè)新對(duì)象,代碼中后半截T1(value)便是placementne
7、w語法中調(diào)用構(gòu)造函數(shù)的寫法,如果傳入的對(duì)象value正是所要求的類型T1,那么這里就相當(dāng)于調(diào)用拷貝構(gòu)造函數(shù)。類似的,因使用了placementnew,編譯器不會(huì)自動(dòng)產(chǎn)生調(diào)用析構(gòu)函數(shù)的代碼,需要手工的實(shí)現(xiàn):與此同時(shí),STL中還有一個(gè)接收兩個(gè)迭代器的destory版本,可將某容器上指定范圍內(nèi)的對(duì)象全部銷毀。典型的實(shí)現(xiàn)方式就是通過一個(gè)循環(huán)來對(duì)此范圍內(nèi)的對(duì)象逐一調(diào)用析構(gòu)函數(shù)。如果所傳入的對(duì)象是非簡單類型,這樣做是必要的,但如果傳入的是簡單類型,或者根本沒有必要調(diào)用析構(gòu)函數(shù)的自定義類型(例如只包含數(shù)個(gè)int成員的結(jié)構(gòu)體),那么再逐一調(diào)用析構(gòu)函數(shù)是沒有必要的,也浪費(fèi)了時(shí)間。為此,STL使用了一種稱為“ty
8、petraits的技巧,在編譯器就判斷出所傳入的類型是否需要調(diào)用析構(gòu)函數(shù):其中value_type()用于取出迭代器所指向的對(duì)象的類型信息,于是:因上述函數(shù)全都是inline的,所以多層的函數(shù)調(diào)用并不會(huì)對(duì)性能造成影響,最終編譯的結(jié)果根據(jù)具體的類型就只是一個(gè)for循環(huán)或者什么都沒有。這里的關(guān)鍵在于_type_traits這個(gè)模板類上,它卞據(jù)不同的T類型定義出不同的has_trivial_destructor的結(jié)果,如果T是簡單類型,就定義為_true_type類型,否則就定義為_false_type類型。其中_true_type、_false_type只不過是兩個(gè)沒有任何內(nèi)容的類,對(duì)程序的執(zhí)行結(jié)
9、果沒有什么意義,但在編譯器看來它對(duì)模板如何特化就具有非常重要的指導(dǎo)意義了,正如上面代碼所示的那樣。_type_traits也是特化了的一系列模板類:如果要把一個(gè)自定義的類型MyClass也定義為不調(diào)用析構(gòu)函數(shù),只需要相應(yīng)的定義_type_traits的一個(gè)特化版本即可:Page模板是比較高級(jí)的C+編程技巧,模板特化、模板偏特化就更是技巧性很強(qiáng)的東西,STL中的type_traits充分借助模板特化的功能,實(shí)現(xiàn)了在程序編譯期通過編譯器來決定為每一處調(diào)用使用哪個(gè)特化版本,于是在不增加編程復(fù)雜性的前提下大大提高了程序的運(yùn)行效率。更詳細(xì)的內(nèi)容可參考STL源碼剖析第二、三章中的相關(guān)內(nèi)容。帶有“的”new
10、和deletechar*s=newchar100;deletes;deletes;MyClass*p=newMyClass10;當(dāng)這樣構(gòu)造成功后,我們可以再將其釋放,釋放時(shí)使用delete:當(dāng)我們對(duì)動(dòng)態(tài)分配的數(shù)組調(diào)用delete時(shí),其行為根據(jù)所申請(qǐng)的變量類型會(huì)有所不同。如果p指向簡單類型,如int、char等,其結(jié)果只不過是這塊內(nèi)存被回收,此時(shí)使用delete口與delete沒有區(qū)別,但如果p指向的是復(fù)雜類型,delete會(huì)針對(duì)動(dòng)態(tài)分配得到的每個(gè)對(duì)象調(diào)用析構(gòu)函數(shù),然后再釋放內(nèi)存。因此,如果我們對(duì)上述分配得到的p指針直接使用delete來回收,雖然編譯期不報(bào)什么錯(cuò)誤(因?yàn)榫幾g器根本看不出來這個(gè)指
11、針p是如何分配的),但在運(yùn)行時(shí)(DEBUG情況下)會(huì)給出一個(gè)Debugassertionfailed提示。classMyClassinta;public:MyClass()printf(ctorn);MyClass()printf(dtorn);void*operatornew(size_tsize)void*p=operatornew(size);printf(callingnewwithsize=%daddress=%pn,size,p);returnp;/主函數(shù)MyClass*mc=newMyClass3;printf(addressofmc=%pn,mc);deletemc;calli
12、ngnewwithsize=003A5A58ctoraddressofmc=dtordtortemplateT*New(intcount)intsize=sizeof(T)*count+4;void*p=T:operatornew(size);*(int*)p=count;T*pt=(T*)(int)p+4);for(inti=0;icount;i+)new(&pti)T();returnpt;templatevoidDelete(T*pt)intcount=(int*)pt)-1;for(inti=0;icount;i+)pti.T();void*p=(void*)(int)pt-4);T:
13、operatordelete(p);把前面類MyClass的代碼稍做修改注釋掉析構(gòu)函數(shù),然后再來看看程序的輸出:ctorctor這一次,new老老實(shí)實(shí)的申請(qǐng)了12個(gè)字節(jié)的內(nèi)存,并且申請(qǐng)的結(jié)果與newoperator返回的結(jié)果也是相同的,看來,是否在前面添加4個(gè)字節(jié),只取決于這個(gè)類有沒有析構(gòu)函數(shù),當(dāng)然,這么說并不確切,正確的說法是這個(gè)類是否需要調(diào)用構(gòu)造函數(shù),因?yàn)槿缦聝煞N情況下雖然這個(gè)類沒聲明析構(gòu)函數(shù),但還是多申請(qǐng)了4個(gè)字節(jié):一是這個(gè)類中擁有需要調(diào)用析構(gòu)函數(shù)的成員,二是這個(gè)類繼承自需要調(diào)用析構(gòu)函數(shù)的類。于是,我們可以遞歸的定義“需要調(diào)用析構(gòu)函數(shù)的類”為以下三種情況之一:2擁有需要調(diào)用析構(gòu)函數(shù)的類的
14、成員的類似的,動(dòng)態(tài)申請(qǐng)簡單類型的數(shù)組時(shí),也不會(huì)多申請(qǐng)4個(gè)字節(jié)。于是在這兩種情況下,釋放內(nèi)存時(shí)使用delete或delete都可以,但為養(yǎng)成良好的習(xí)慣,我們還是應(yīng)該注意只要是動(dòng)態(tài)分配的數(shù)組,釋放時(shí)就使用delete。釋放內(nèi)存時(shí)如何知道長度p=s;alloc0bytes,address=003A36F0distance=3815152alloc8bytes,address=003A3710distance=16alloc16bytes,address=003A3738distance=24alloc24bytes,address=003A84E0distance=32alloc32bytes,address=003A8528distance=40每一次分配的字節(jié)數(shù)都比上一次多4,distance值記錄著與上一次分配的差值,第一個(gè)差值沒有實(shí)際意義,中間有一個(gè)較大的差值,可能是這塊內(nèi)存已經(jīng)被分配了,于是也忽略它。結(jié)果中最小的差值為16字節(jié),直到我們申請(qǐng)16字節(jié)時(shí),這個(gè)差值變成了24,后面也有類似的規(guī)律,那么我們可以認(rèn)為申請(qǐng)所得的內(nèi)存結(jié)構(gòu)是如下這樣的:圖中右邊為每次分配所
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 一次函數(shù)知識(shí)點(diǎn)總結(jié)
- 一元一次不等式的解法(提高)知識(shí)講解
- 【高考政治必考知識(shí)點(diǎn)總結(jié)】高考政治知識(shí)點(diǎn)
- 雙輥式破碎機(jī)行業(yè)深度研究報(bào)告
- 【英語】英語總復(fù)習(xí)∶八年級(jí)英語上冊閱讀理解(提高)知識(shí)講解及答案經(jīng)典
- 物流園節(jié)能評(píng)估報(bào)告
- 2025年單滴行列式制瓶機(jī)項(xiàng)目可行性研究報(bào)告
- 2025年中國醫(yī)用干式激光相機(jī)行業(yè)發(fā)展監(jiān)測及投資前景展望報(bào)告
- 合伙合同范本個(gè)體
- 庭院配套銷售合同范本
- 文學(xué)類文本閱讀(語言賞析類)-2025年北京高考語文一輪總復(fù)習(xí)(解析版)
- 2024年政工職稱考試題庫(含答案)
- 香港(2024年-2025年小學(xué)二年級(jí)語文)部編版綜合練習(xí)試卷(含答案)
- 專題18 圓的相關(guān)性質(zhì)及計(jì)算證明(34題)2024年中考數(shù)學(xué)真題分類匯編(解析版)
- 2024羽毛球教案36課時(shí)
- 1.1區(qū)域及其類型-課件
- 小學(xué)生衛(wèi)生知識(shí)健康教育精課件
- 小學(xué)生課程表模板可編輯78
- 營養(yǎng)科專業(yè)知識(shí)考核試卷
- NB-T47044-2014電站閥門-標(biāo)準(zhǔn)
- 安全技術(shù)管理專業(yè)畢業(yè)實(shí)習(xí)報(bào)告范文
評(píng)論
0/150
提交評(píng)論