在函數返回類型前加上關鍵字inline就可以將函數指定為內聯函數:
1 inline const string& shortString(const string &s1, const string &s2) { 2 return s1.size() < s2.size() ? s1 : s2; 3 }
函數指定為內聯函數,(通常)就是將它在程序調用點上”內聯地“展開。假設我們將shortString定義為內聯函數,則調用:
1 cout<<shortString(s1,s2)<<endl;
在編譯時展開為:
1 cout<<(s1.size() < s2.sizre() ? s1 : s2)<<endl;
將函數聲明為內聯的方法:
1. 在函數返回類型前加inline(inline return_type function(parameters))。成員函數可以在聲明時候添加inline也可以在定義時候添加inline。
2. 將成員函數定義在類定義式內,這個成員函數就被隱喻聲明為inline.
內聯說明(inline specification)對於編譯器來說只是一個建議,編譯器可以忽略這個建議。
將內聯函數放入頭文件內:
內聯函數的定義應該在頭文件中定義。因為大多數建置環境(build environments)在編譯過程中進行inlining.而為了將一個“函數調用”替換為“被調用函數的本體”,編譯器必須知道那個函數長什么樣子。僅有函數聲明是不夠的;而且內聯函數有可能在程序中定義不止一次,這時必須保證在所有源文件中,其定義是完全相同的。把內聯函數的定義放在頭文件中,可以確保在調用函數的時候所使用的定義是相同的。
內聯函數的優點:
可以避免調用函數的開銷。當函數體比較小的時候,內聯函數可以令目標代碼更加高效。對於存取函數以及其他一些比較短的關鍵執行函數。
內聯函數的缺點:
1. 由於將對函數的每一個調用都以函數本體替換之。所以會增加目標代碼的大小。造成代碼膨脹。這將導致程序體積太大,不利於在內存不大的機器上運行。
2. inline函數無法隨着程序庫的升級而升級。如果程序庫中包含內聯函數,一旦內聯函數被改變,那么所有用到程序庫的客戶端程序都要重新編譯。如果函數不 是內聯函數,一旦它有任何修改,客戶端只需要重新連接就好,遠比誠信編譯的負擔少的多。在頭文件加入或修改內聯函數時,使用該頭文件的所有源文件都必 須重新編譯。
3. 很多調試器無法調試內聯函數。很多建置環境僅僅只能”在調試板程序中禁止發生inlining“
一般來說,內聯機制適用於優化小的、只有幾行的而且經常被調用的函數。一個比較得當的處理規則是,不要內聯超過10行的函數。只有當函數10行甚至更少時才會將其定義為內聯函數。
不適用的情況:
1. 大多數編譯器不支持遞歸函數的內聯
2. 包含循環或switch語句的函數是得不償失的,除非在大多數情況下,這些循環或switch語句從不執行。
3. 虛函數
大部分編譯器將太過復雜的函數inling,而所有堆virtual函數的調用(除非是最平淡無奇的)也都會使inling落空。因為virtual意味“等待,知道運行期才確定調用哪個函數”而inline意味着“執行前,先將調用動作替換為被執行函數的本體”。如果編譯器不知道該調用哪個函數,你就很難責備它們拒絕將函數本體inlining。
4. 構造函數和析構函數
編譯器會為構造函數和析構函數插入許多代碼。