C++中的內聯函數

C++中的內聯函數

1. 定義

內聯函數是C++的增強特性之一,用來降低程序的運行時間。當內聯函數收到編譯器的指示時,即可發生內聯:編譯器將使用函數的定義體來替代函數調用語句,這種替代行爲發生在編譯階段而非程序運行階段

它們看起來像函數,運作起來像函數,比宏要好得多,使用時還不需要承擔函數調用的開銷。當內聯一個函數時,編譯器可以對函數體執行特定環境下的優化工作,這樣的優化對”正常“的函數調用是不可能的

下面是一個實例,使用內聯函數來返回兩個數中的最大值:

#include <iostream>
 
using namespace std;
 
inline int Max(int x, int y)
{
   return (x > y)? x : y;
}
 
// 程序的主函數
int main( )
{
 
   cout << "Max (20,10): " << Max(20,10) << endl;
   cout << "Max (0,200): " << Max(0,200) << endl;
   cout << "Max (100,1010): " << Max(100,1010) << endl;
   return 0;
}

上面的代碼運行後結果爲:

Max (20,10): 20
Max (0,200): 200
Max (100,1010): 1010

2. 細節

  • 內聯函數的關鍵字爲inline

  • 內聯函數是一個對編譯器的建議,如果函數過於複雜,編譯器會不接受你的建議而將函數處理成普通的函數

  • 對內聯函數進行任何修改,都需要重新編譯函數的所有客戶端,因爲編譯器需要重新更換一次所有的代碼,否則將會繼續使用舊的函數

  • inline關鍵字必須和函數體定義放在一起纔可以實現內聯,僅僅將inline放在函數聲明之前不起任何作用。inline是一個用於實現的關鍵字而不是一個用於聲明的關鍵字

    注意:這個說法是《高質量程序設計指南C++/C語言》中的說法,在《C++Primer》中提到應在函數的聲明與定義中都加inline

    《高質量程序設計指南C++/C語言》:

    關鍵字inline 必須與函數定義體放在一起才能使函數成爲內聯,僅將inline 放在函數聲明前面不起任何作用

    如下風格的函數Foo 不能成爲內聯函數:

    inline void Foo(int x, int y); // inline 僅與函數聲明放在一起

    void Foo(int x, int y){}

    而如下風格的函數Foo 則成爲內聯函數:

    void Foo(int x, int y);

    inline void Foo(int x, int y) // inline 與函數定義體放在一起{}

    所以說,inline 是一種“用於實現的關鍵字”,而不是一種“用於聲明的關鍵字”。一般地,用戶可以閱讀函數的聲明,但是看不到函數的定義。儘管在大多數教科書中內聯函數的聲明、定義體前面都加了inline 關鍵字,但我認爲inline 不應該出現在函數的聲明中。這個細節雖然不會影響函數的功能,但是體現了高質量C++/C 程序設計風格的一個基本原則:聲明與定義不可混爲一談,用戶沒有必要、也不應該知道函數是否需要內聯。

  • 在類中定義的成員函數將自動轉化爲內聯函數

    注意:必須要在類內完成函數定義纔會轉化成內聯函數,在類內聲明而在類外定義則不會轉化,當然只有函數非常簡單時編譯器纔會處理成內聯函數

  • 虛函數不允許內聯

  • 在調試時查看彙編會發現內聯函數還是使用了call指令進行了函數調用而沒有用在調用處展開的方式處理,這是因爲debug版本上inline是不起作用的;inline只有在release版本下才能出現

3. 內聯函數的優缺點分析

優點:

  1. 它通過避免函數調用所帶來的開銷來提高你程序的運行速度
  2. 當函數調用發生時,它節省了變量壓棧、出棧的開銷
  3. 它避免了一個函數執行完返回原現場的開銷
  4. 通過將函數聲明爲內聯,可以把函數定義放在頭文件內

缺點:

  1. 因爲代碼的擴展,內聯函數增大了可執行程序的體積
  2. C++內聯函數的展開是編譯階段,這就意味着如果內聯函數發生了改動,那麼就需要重新編譯代碼
  3. 當把內聯函數放在頭文件中時,它將會使頭文件的信息變多
  4. 有時候內聯函數並不受到青睞,比如在嵌入式系統中,嵌入式系統的存儲約束可能不允許體積很大的可執行程序

4.內聯函數和宏的區別

  1. 內聯函數在運行時可調試,而宏不可以
  2. 編譯器會對內聯函數的參數類型做安全檢查或自動類型轉換(同普通函數),而宏則不會
  3. 內聯函數可以訪問類的成員變量,宏則不能
  4. 在類中定義的成員函數,自動轉化爲內聯函數
  5. inline在和宏相比沒有付出任何額外代價的的情況下更安全,《Effective C++》中”Prefer consts,enums,and inlines to #defines“以及《高質量程序設計指南C++/C語言》中”用函數內聯取代宏“都建議用inline函數代替帶參宏
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章