![關(guān)于函數(shù)的高級專題_第1頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/19/60a779b4-37bc-4134-b0f8-95730a994baa/60a779b4-37bc-4134-b0f8-95730a994baa1.gif)
![關(guān)于函數(shù)的高級專題_第2頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/19/60a779b4-37bc-4134-b0f8-95730a994baa/60a779b4-37bc-4134-b0f8-95730a994baa2.gif)
![關(guān)于函數(shù)的高級專題_第3頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/19/60a779b4-37bc-4134-b0f8-95730a994baa/60a779b4-37bc-4134-b0f8-95730a994baa3.gif)
![關(guān)于函數(shù)的高級專題_第4頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/19/60a779b4-37bc-4134-b0f8-95730a994baa/60a779b4-37bc-4134-b0f8-95730a994baa4.gif)
![關(guān)于函數(shù)的高級專題_第5頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/19/60a779b4-37bc-4134-b0f8-95730a994baa/60a779b4-37bc-4134-b0f8-95730a994baa5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、第7章 關(guān)于函數(shù)的高級專題 合理使用函數(shù)能將程序模塊化,大大降低了問題的規(guī)模,提高了編碼效率,方便以后復(fù)用代碼。函數(shù)的參數(shù)傳遞有傳值,傳指針和傳引用3種方式,從類型的角度上看,參數(shù)不僅僅可以是系統(tǒng)內(nèi)建的數(shù)據(jù)類型,還可以是數(shù)組、結(jié)構(gòu)以及后面要介紹的類對象等等,同時,內(nèi)存使用注意事項、函數(shù)與指針的關(guān)系也是學(xué)習(xí)C+必須邁過的檻。7.1 內(nèi)存使用錯誤剖析 編寫代碼時,少不了和內(nèi)存打交道,很多程序員對此提心吊膽,稱內(nèi)存為“雷區(qū)”或“bug集中營”似乎并不過份。即使是久經(jīng)沙場的老手,有時也難免落入內(nèi)存錯誤的陷阱。本節(jié)幫助讀者了解這些常見的錯誤,在編程時加以注意,把出錯的概率降到最低。7.1.1 內(nèi)存泄露使
2、用new或malloc()動態(tài)申請的內(nèi)存,如果不再使用,應(yīng)該把它釋放掉,為程序節(jié)省內(nèi)存空間,方便后面的使用。在C/C+中,內(nèi)存管理器不會自動回收不再使用的內(nèi)存。如果忘記釋放不再使用的內(nèi)存,在程序的運行過程中,這些內(nèi)存就不能再被使用用,就造成了所謂的“內(nèi)存泄露”。內(nèi)存泄露是最為常見的錯誤,現(xiàn)在的計算機配置比較高,內(nèi)存容量很大,一兩處內(nèi)存泄露通常不至于讓程序崩潰,也不會出現(xiàn)邏輯上的錯誤,進程退出時,系統(tǒng)會自動釋放該進程所有相關(guān)的內(nèi)存,所以內(nèi)存泄露的后果相對來說并不是災(zāi)害性的。但這并不意味著完全沒有危險,如果程序規(guī)模較大、長時間運行,或者是內(nèi)存資源相對緊張的場合,內(nèi)存泄露過多會導(dǎo)致內(nèi)存耗盡,系統(tǒng)沒有
3、后繼內(nèi)存可以使用,程序可能會崩潰。第6章講過,代碼塊中聲明的局部變量在代碼塊執(zhí)行完畢后會自動消亡,那如果是在代碼塊中申請的動態(tài)內(nèi)存,系統(tǒng)會自動回收么,答案是否定的,如:if ( condition condition )int* p = new int8;7.1.2 野指針前面提到“指針消亡,并不意味著其指向的內(nèi)存會被自動釋放”,同樣“釋放動態(tài)內(nèi)存,并不意味著指針會消亡,也不意味著指針的值會改變”,如:int* p=new int8;delete p;指向完delete p后,指針p是不是就自動消亡了呢,錯,不論是使用delete/delete還是使用free(),指針p非但不會消亡,其值也保
4、持不變,并不會變?yōu)閚ull。這時,使用“if (p!=null)”進行處理也無法起到防錯作用。為此,指針被free或delete/delete后,一定要置為null,沒有置為null的指針常稱為“野指針”,釋放掉的堆內(nèi)存會被內(nèi)存管理器重新分配,野指針指向的內(nèi)存已經(jīng)被賦予新的意義。如果使用野指針釋放或再次訪問這塊內(nèi)存,會給程序帶來災(zāi)難性的后果。7.1.3 試圖修改常量 程序中出現(xiàn)的字符串常量和其他全局常量(如全局const常量),是存放在.rodata里面的,.rodata內(nèi)存頁面是不能修改的,試圖對常量修改,會引發(fā)內(nèi)存錯誤,如代碼7 2 。7.1.4 用錯sizeof運算符sizeof()可以
5、計算數(shù)組的大小(字節(jié)數(shù)),但對指針來說,sizeof僅僅得到指針變量的字節(jié)數(shù)。但當數(shù)組作為函數(shù)的參數(shù)進行傳遞時,數(shù)組退化為同類型的指針,用sizeof是無法取得數(shù)組的大小的。代碼7 3演示了sizeof的用法:7.1.5 內(nèi)存越界訪問使用指針和數(shù)組訪問某塊內(nèi)存區(qū)域時,編譯器并不會對數(shù)組下標是否越界、指針是否有效進行檢查,如果不注意,很容易造成內(nèi)存越界訪問的錯誤,內(nèi)存越界訪問有兩種:一種是讀越界,一種是寫越界,常稱作緩沖區(qū)溢出。讀越界,即讀了不屬于自己的數(shù)據(jù),如果所讀的內(nèi)存地址是無效的,程序會立刻崩潰,但如果所讀內(nèi)存地址是有效的,在讀的時候不會出問題,但讀到的數(shù)據(jù)是隨機的,會產(chǎn)生不可預(yù)料的后果。
6、寫越界,即往不該寫的內(nèi)存地址空間中寫了東西,這往往會給程序帶來很多匪夷所思的錯誤和BUG,有些癥狀是隨機的,時有時無,給問題分析帶來很多的困難。一些輔助工具可以幫忙檢查內(nèi)存越界,但從根本上說,在編程時應(yīng)十分小心,特別是對于外部傳入的參數(shù)要仔細檢查,另外,要做好程序的防錯處理。7.1.6 變量的初始化 不論是指針變量,還是普通變量,一定要時刻牢記“初始化”,雖然編譯器會對有的變量自動初始化為0,但在聲明變量時就對它進行初始化,是一個編程的好習(xí)慣,還要重視編譯器的警告信息,發(fā)現(xiàn)有引用未初始化的變量,立即修改過來。7.2 重申:函數(shù)參數(shù)傳遞和返回機制 前面已經(jīng)提及,函數(shù)的參數(shù)傳遞有值傳遞、指針傳遞和
7、引用傳遞,函數(shù)返回也可是返回值、返回指針或返回引用。拋開引用傳遞,對值和指針,不論是參數(shù)傳遞還是函數(shù)返回,理解“副本”的概念十分重要。7.2.1 參數(shù)傳遞時的“副本”先來看一下函數(shù)調(diào)用的過程,不論是值傳遞還是指針傳遞,編譯器都要為每個函數(shù)制作臨時副本,函數(shù)體中對參數(shù)的修改都是對副本的修改,對傳值調(diào)用來說,對副本的任何操作不會對傳入的參數(shù)對象有任何的影響,這很好理解,但對傳指針調(diào)用來說,情況稍顯復(fù)雜,很多人對此存在誤解。指針參數(shù)傳遞的示例代碼見代碼7 4。7.2.2 函數(shù)返回時的“副本”函數(shù)執(zhí)行完畢后,函數(shù)內(nèi)部聲明的局部變量會自動消亡,對應(yīng)的內(nèi)存被釋放,由內(nèi)存管理器收回,但返回值會被放置(復(fù)制)
8、到指定位置(可能是CPU寄存器,也可能是某個內(nèi)存單元),然后上級函從這個位置取得返回值。這個位置,可以看成是函數(shù)返回值的“副本”,這解釋了為什么可以用“return 局部變量;”來返回一個值,示例見代碼7 6。7.3 函數(shù)與指針 在前面的章節(jié)中已經(jīng)介紹了函數(shù)的傳指針參數(shù)調(diào)用,返回指針,根據(jù)數(shù)組名和指針的等價性,函數(shù)的參數(shù)也可以是數(shù)組,在這些基本概念的基礎(chǔ)上,本節(jié)討論指向函數(shù)的指針以及帶參主函數(shù)的相關(guān)內(nèi)容。7.3.1 指向函數(shù)的指針 函數(shù)是一組代碼的封裝體,這組代碼在內(nèi)存中占有一片存儲空間,該空間的起始地址存放在以函數(shù)名為名的單元的,換言之,函數(shù)名就是指向函數(shù)的常指針,這有點類似于數(shù)組名是指向數(shù)
9、組內(nèi)存空間的常指針。 (1)函數(shù)指針的聲明和初始化 (2)函數(shù)指針使用舉例7.3.2 typedef為了避免讀者對typedef的用法產(chǎn)生誤解,前面一直沒有介紹typedef的相關(guān)內(nèi)容,介紹完函數(shù)指針,來看看typedef的相關(guān)內(nèi)容。typedef用來給一個已經(jīng)存在的類型聲明一個別名,舉一個最簡單的例子:typedef int* int_p;/不要忘記分號typedef為int* 引入了一個新的助記符int_p,可以在程序中使用int_p聲明指向int型變量的指針,如:int_p pA,pB;上述代碼聲明了兩個int型指針變量pA和pB,應(yīng)當注意:typedef不同于編譯預(yù)處理命令define
10、,這種不同主要體現(xiàn)在兩個方面:(1)#define是預(yù)處理指令,在編譯預(yù)處理時進行簡單的替換,不做正確性檢查,不管含義,只是簡單的替換,如:#define PI 3.14(2)define結(jié)構(gòu)可以抽象為:define A B7.3.3 通過函數(shù)指針將函數(shù)作為另一個函數(shù)的參數(shù)函數(shù)指針的一個功用是把函數(shù)地址作為參數(shù)傳送,以提高函數(shù)的通用性和靈活性,如代碼7 10 :7.3.4 函數(shù)指針數(shù)組 指向函數(shù)的指針還可以組成指針數(shù)組,稱為函數(shù)指針數(shù)組。函數(shù)指針數(shù)組的使用范例見代碼: (詳細內(nèi)容請參照本書)7.3.5 返回函數(shù)指針的函數(shù)和普通指針一樣,函數(shù)指針也可以作為另一個函數(shù)的返回值,如代碼7 12:7.
11、4 函數(shù)與數(shù)組 前面已經(jīng)討論過數(shù)組和指針的關(guān)系,知道數(shù)組名實際上是指向數(shù)組所占內(nèi)存單元的常指針,由此可知,和指針一樣,數(shù)組既可以作函數(shù)的參數(shù),也可以作函數(shù)的返回值。7.4.1 數(shù)組名作函數(shù)參數(shù) 數(shù)組名用作函數(shù)參數(shù)時,用以向程序傳遞數(shù)組所占內(nèi)存單元的首地址,數(shù)組名參數(shù)與指針參數(shù)的用法幾乎完全一致。有數(shù)組參數(shù)的函數(shù)原型的一般形式為: 返回類型 函數(shù)名(數(shù)組名 ,其他參數(shù)) 習(xí)慣上在參數(shù)列表中要指明數(shù)組元素的個數(shù),在本章前面已經(jīng)說明,在函數(shù)內(nèi)部使用sizeof(數(shù)組名)返回的只是指針大小,而不是數(shù)組大小,因此,在參數(shù)列表中顯式注明數(shù)組元素的個數(shù)是個好的編程習(xí)慣,當然,如果能保證不會出現(xiàn)越界訪問的情況
12、,這個參數(shù)可以省略。理論上,“數(shù)組名”中是空的,沒有數(shù)字,如果在其中寫明元素大小,編譯器也不予理會,不會做錯誤檢驗。7.4.2 通過指針得到多于1個的回傳值 理論上說,C+函數(shù)最多只能有1個返回值(return返回值),因此,由函數(shù)返回數(shù)組似乎是不可能的,實際上,使用指針可以使函數(shù)得到多于1個回傳值。 (1)返回指針變量 返回指針變量,便可以對指針指向的一片內(nèi)存區(qū)域進行讀寫,需要注意的是:不可返回指向棧內(nèi)存的指針,否則會出現(xiàn)“野指針”內(nèi)存錯誤。 (2)通過指針參數(shù)修改多個變量的值。7.5 函數(shù)與結(jié)構(gòu)體、共用體及類對象 前面已經(jīng)講過結(jié)構(gòu)體和共用體的概念,結(jié)構(gòu)體和共用體將數(shù)據(jù)整合為一個單獨的實體。
13、結(jié)構(gòu)體變量、共用體變量以及后面要介紹到的類對象,用法都接近于普通的變量,對結(jié)構(gòu)體變量、共用體變量和類對象來說,函數(shù)支持其傳值、傳指針和傳引用調(diào)用,同時,函數(shù)可返回結(jié)構(gòu)體變量、共用體變量和類對象,也可返回指向這些變量的指針和引用。 下面以結(jié)構(gòu)體來討論使用方式,共用體和類對象與結(jié)構(gòu)體在函數(shù)調(diào)用和返回的機制上是一致的。7.5.1 3種參數(shù)調(diào)用 同其他變量一樣,結(jié)構(gòu)變量也可以作為函數(shù)的參數(shù),請看代碼。 (詳細內(nèi)容請參照本書)7.5.2 3種返回機制 函數(shù)的返回機制同樣有返回結(jié)構(gòu)變量,返回指向結(jié)構(gòu)變量的指針和返回引用3種方式,和參數(shù)傳遞一樣,返回結(jié)構(gòu)變量需要復(fù)制“結(jié)果”,浪費時間和空間,傳遞指針和引用能
14、有效提高效率,詳細的用法與第6章中講述的普通變量的3種返回機制完全一致。7.6 函數(shù)編寫的建議 本節(jié)簡單討論下如何寫出高效,不易出錯的代碼,當然,這些建議只是最基本的幾條,在網(wǎng)絡(luò)上或者專門討論C+編程技巧的教材中,討論函數(shù)編寫原則和建議的篇幅是這里的幾十倍,這里權(quán)當是拋磚引玉,有效與否還靠讀者的理解和檢驗。7.6.1 合理使用const在指針傳遞或引用傳遞時,如果參數(shù)僅僅是輸入用,則應(yīng)在類型前加const,以防止指針在函數(shù)體內(nèi)被意外修改,若輸入?yún)?shù)采用“值傳遞”方式,函數(shù)將自動產(chǎn)生臨時變量用于復(fù)制該參數(shù),該參數(shù)本就不需要保護,不用const修飾。 對于非內(nèi)部數(shù)據(jù)類型的輸入?yún)?shù),尤其是占內(nèi)存字節(jié)
15、較多的參數(shù),應(yīng)該將“值傳遞”改為“const引用傳遞”,以提高效率。但對內(nèi)部數(shù)據(jù)類型的輸入?yún)?shù)而言,不要將“值傳遞”的方式改為“const引用傳遞”。否則既達不到提高效率的目的,又降低了函數(shù)的可理解性。C+中,返回值也可用const修飾,這樣,在返回引用或指針時,不允許使用如下述代碼的形式對返回值改寫:函數(shù)名(參數(shù)表)表達式;7.6.2 檢查輸入?yún)?shù)的有效性 很多函數(shù)代碼本身并沒有太大問題,常常是輸入?yún)?shù)出錯或出現(xiàn)了沒有考慮到的情況,推薦的檢查方式是采用assert宏,關(guān)于assert宏的詳細介紹請參考第20章。此外,還要檢查一些全局變量、指針等是否有效。7.6.3 函數(shù)返回類型的判斷 返回值是傳值、傳指針還是傳引用,在函數(shù)設(shè)計和編寫過程中要規(guī)劃好。這不僅牽扯到函數(shù)返回的效率,而且還要保證返回的指針和引用指向的不是棧內(nèi)存,否則,極容易形成“野指針”。7.7 小結(jié)本章討論了一些和函數(shù)相關(guān)的相對高階的內(nèi)容,以前面幾章的內(nèi)容為基礎(chǔ),首先介紹了C+程序中經(jīng)常出現(xiàn)的內(nèi)存錯誤,這往往是很多初學(xué)者忽略的東西,結(jié)果讓程序到處是漏洞,無從運行。對函數(shù)參數(shù)傳遞和返回機制進行了“重申”,理解“副本”的概念,不論是傳值還是傳指針調(diào)用,都存在“復(fù)制品”,不同的是傳指針僅僅復(fù)制指針變量占據(jù)的4個字節(jié)(某些系統(tǒng)是2個字節(jié)),效率相比傳值調(diào)用要高
溫馨提示
- 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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 發(fā)展學(xué)生的邏輯思維和思維方法考核試卷
- 城市規(guī)劃城市空氣質(zhì)量改善考核試卷
- 放射性金屬礦選礦廠設(shè)計與建設(shè)考核試卷
- 團隊沖突管理與和諧關(guān)系的構(gòu)建考核試卷
- 建筑通風(fēng)設(shè)備安裝與效果調(diào)試考核試卷
- 2025年01月吉安縣專職文明實踐員筆試歷年典型考題(歷年真題考點)解題思路附帶答案詳解
- 摩托車防霧燈安裝與調(diào)試考核試卷
- 現(xiàn)代醫(yī)療技術(shù)下的高純度氧氣制備技術(shù)
- 園藝機具在新能源領(lǐng)域的應(yīng)用考核試卷
- 環(huán)??萍寂c生態(tài)旅游的融合發(fā)展
- 2024-2030年一次性治療服裝市場發(fā)展現(xiàn)狀分析及行業(yè)投資戰(zhàn)略研究報告
- 2024年云南省中考數(shù)學(xué)模擬試卷(三)
- 信息系統(tǒng)安全等級保護(一級)基本要求
- 2024年襄陽漢江檢測有限公司招聘筆試參考題庫附帶答案詳解
- 2021利達JB-QG-LD988EL JB-QT-LD988EL 火災(zāi)報警控制器 消防聯(lián)動控制器調(diào)試手冊
- 九下名著閱讀《儒林外史》考點+人物分析+中考真題
- 醫(yī)院檢驗科安全風(fēng)險評估報告表單
- 第23課《出師表》課件(共48張)
- 高一北師大版歷史必修一知識點總結(jié)9篇
- 夏普LCD-46LX750A電視機使用說明書
- 2024年山東魯商集團有限公司招聘筆試參考題庫含答案解析
評論
0/150
提交評論