深入理解內聯函式

2021-09-29 14:27:51 字數 1623 閱讀 2904

內聯函式,看起來像是函式,運作起來像是函式,比巨集要好得多(巨集沒有錯誤檢查等缺點),使用時還不需要承擔函式呼叫的開銷。

基本思想:

將每個函式呼叫以它的**來替換。

但這種做法很可能會增加整個目標**的體積。在一台記憶體有限的計算機裡,過分地使用內聯所產生的程式會因為有太大的體積導致可用空間不夠。即使可以使用虛擬記憶體,內聯造成的**膨脹也可能會導致不合理的頁面排程行為(系統顛簸),這將使你的程式執行慢得象在爬。(當然,它也為磁碟控制器提供了乙個極好的鍛鍊方式:))過多的內聯還會降低指令快取記憶體的命中率,從而使取指令的速度降低,因為從主訪問指令當然比從快取要慢。

另一方面,如果內聯函式體非常短,編譯器為這個函式體生成的**就會真的比為函式呼叫生成的**要小許多。如果是這種情況,內聯這個函式將會

確實帶來更小的目標**和更高的快取命中率!

inline 指令就象 register,它只是對編譯器的一種提示,而不是命令。也就是說,只要編譯器願意,它就可以隨意地忽略掉你的指令,事實上編譯器常常會這麼做。例如,大多數編譯器拒絕內聯"複雜"的函式(例如,包含迴圈和遞迴的函式);還有,即使是最簡單的虛函式呼叫,編譯器的內聯處理程式對它也愛莫能助。(這一點也不奇怪。virtual 的意思是"等到執行時再決定呼叫哪個函式",inline 的意思是"在編譯期間將呼叫之處用被調函式來代替",如果編譯器甚至還不知道哪個函式將被呼叫,當然就不能責怪它拒絕生成內聯呼叫了)。

乙個給定的內聯函式是否真的被內聯取決

於所用的編譯器的具體實現。幸運的是,大多數編譯器都可以設定診斷級,當

宣告為內聯的函式實際上沒有被內聯時,編譯器就會為你發出警告資訊

如果在乙個標頭檔案中定義乙個內聯函式,但編譯器並不將其作為內聯,稱其為被外聯的內聯。當cpp檔案包含該標頭檔案被編譯時,生成的目標檔案中將包含乙個該函式,就像該函式沒有被宣告為inline一樣,但是將多個這樣的cpp檔案的目標檔案鏈結在一起時,編譯器就會因為程式中有兩個同名的函式定義而報錯。

為了防止該問題,舊規則規定,對於未被內聯的內聯函式,編譯器將其當成被宣告為static那樣處理,即,使他侷限於當前被編譯得檔案。這一策略消除了鏈結時的錯誤,但帶來了開銷,每個包含該函式的被編譯單元都包含有自己的該函式的靜態拷貝。並且,當該函式內部定義了區域性靜態變數,那麼,每乙個該函式的拷貝都有此區域性變數的乙份拷貝(一般來說,函式中的static意味著只有乙份拷貝)。

某些情況下,編譯器將內聯函式確實內聯了,此時,如果程式中要取乙個內聯函式的位址,編譯器就必須為此生成乙個函式體(畢竟內聯函式是替換,不是真的函式)。這在舊的規則下,每個取用內聯函式位址的被編譯單元還是各自生成了此函式的靜態拷貝。

假設寫了某個函式 f 並宣告為 inline,如果出於什麼原因,編譯器決定不對

它內聯,那將會發生些什麼呢?最明顯的乙個回答是將 f 作為乙個非內聯函式

來處理:為 f 生成**時就象它是乙個普通的"外聯"函式一樣, 對 f 的呼叫也

象對普通函式呼叫那樣進行。

而且當程式中需要使用內聯函式的位址時,不管涉及的被編譯單元有多少,將只生成唯一乙個內聯函式的外部拷貝。這種特性加到c++標準的時間相對較晚,但現在的編譯器基本都支援。

找出程式中那些重要的函式(二八法則:80%的時間執行的20%的**),以及哪些內聯後確實可以提高程式效能的函式,將其宣告為內聯。同時,還需要注意**膨脹帶來的問題,並監視編譯器的警告資訊,看看內聯函式是否真的被編譯器內聯。

深入理解函式

第五章 深入理解函式 1.return語句 有返回值的函式中,return語句的作用式提供整個函式的返回值,並結束當前函式返回到呼叫它的地方。在沒有返回值的函式中也可以使用return語句,例如當前檢查到乙個錯誤時提前結束當前函式的執行並返回 這個函式首先檢查引數x是否大於0,如果x不大於0就列印錯...

深入理解指標函式

1.指標函式的定義 顧名思義,指標函式即返回指標的函式。其一般定義形式如下 型別名 函式名 函式引數表列 其中,字尾運算子括號 表示這是乙個函式,其字首運算子星號 表示此函式為指標型函式,其函式值為指標,即它帶回來的值的型別為指標,當呼叫這個函式後,將得到乙個 指向返回值為 的指標 位址 型別名 表...

深入理解指標函式

顧名思義,指標函式 即返回指標的函式。其一般定義形式如下 型別名 函式名 函式引數表列 其中,字尾運算子括號 表示這是乙個函式,其字首運算子星號 表示此函式為指標型函式,其函式值為指標,即它帶回來的值的型別為指標,當呼叫這個函式後,將得到乙個 指向返回值為 的指標 位址 型別名 表示函式返回的指標指...