C++內聯函數

一、基本定義

       inline是C++語言中的一個關鍵字,可以用於程序中定義內聯函數,inline的引進使內聯函數的定義更加簡單。說到內聯函數,這裏給出比較常見的定義,內聯函數是C++中的一種特殊函數,它可以像普通函數一樣被調用,但是在調用時並不通過函數調用的機制而是通過將函數體直接插入調用處來實現的,這樣可以大大減少由函數調用帶來的開銷,從而提高程序的運行效率。一般來說inline用於定義類的成員函數。

二、inline的基本使用

      inline的使用比較簡單,只需要在聲明或者定義函數時在頭部加上inline關鍵字即可,格式如下

inline 返回值類型  函數名 (函數參數)
{
    //此處定義函數體
}

 一般來說,inline適用的函數有兩種,一種是在類內定義的成員函數,另一種是在類內聲明,類外定義的成員函數,對於這兩種情況inline的使用有一些不同:

(1)類內定義成員函數

  這種情況下,我們可以不用在函數頭部加inline關鍵字,因爲編譯器會自動將類內定義的函數聲明爲內聯函數,代碼如下:

class temp
{
public:
    int  amount;

    //構造函數
    temp(int amount)
    {
        this->amount = amount;
    }
  
    //普通成員函數,在類內定義時前面可以不加inline
    void print_amount()
    {
        cout << this-> amount;
    }
}

 從上面的代碼可以看出,在類內定義函數時,可以不加inline關鍵字,編譯器會自動將類內定義的函數(構造函數、析構函數、普通成員函數等)設置爲內聯,具有內聯函數調用的性質。

(2) 類內聲明函數,在類外定義函數

    根據C++編譯器的規則,這種情況下如果想將該函數設置爲內聯函數,則可以在類內聲明時不加inline關鍵字,而在類外定義函數時加上inline關鍵字,代碼如下所示:

class temp
{
public:
    int  amount;

    //構造函數
    temp(int amount)
    {
        this->amount = amount;
    }
  
    //普通成員函數,在類內聲明時前面可以不加inline
    void print_amount()
}

//在類外定義函數體,必須在前面加上inline關鍵字
inline void temp:: print_amount()
{
    cout << amount << endl;
}

從上面代碼我們可以看出,類內聲明可以不用加上inline關鍵字,但是類外定義函數體時必須要加上,這樣才能保證編譯器能夠識別其爲內聯函數。

    另外,我們可以在聲明函數和定義函數的同時寫inline,也可以只在函數聲明時加inline,而定義函數時不加inline。只要在調用該函數之前把inline的信息告知編譯系統,編譯系統就會在處理函數調用時按內聯函數處理。也就是說,上面說的幾種方法都可以實現一個內聯函數的定義,根據自己的需要來寫即可。

三、內聯函數的優缺點

  優點:

1.inline 定義的類的內聯函數,函數的代碼被放入符號表中,在使用時直接進行替換,(像宏一樣展開),沒有了調用的開銷,效率也很高。

2.很明顯,類的內聯函數也是一個真正的函數,編譯器在調用一個內聯函數時,會首先檢查它的參數的類型,保證調用正確。然後進行一系列的相關檢查,就像對待任何一個真正的函數一樣。這樣就消除了它的隱患和侷限性。(宏替換不會檢查參數類型,安全隱患較大)

3.inline函數可以作爲一個類的成員函數,與類的普通成員函數作用相同,可以訪問一個類的私有成員和保護成員。內聯函數可以用於替代一般的宏定義,最重要的應用在於類的存取函數的定義上面。

  缺點:

1.內聯函數具有一定的侷限性,內聯函數的函數體一般來說不能太大,如果內聯函數的函數體過大,一般的編譯器會放棄內聯方式,而採用普通的方式調用函數。(換句話說就是,你使用內聯函數,只不過是向編譯器提出一個申請,編譯器可以拒絕你的申請)這樣,內聯函數就和普通函數執行效率一樣了。

2.inline說明對編譯器來說只是一種建議,編譯器可以選擇忽略這個建議。比如,你將一個長達1000多行的函數指定爲inline,編譯器就會忽略這個inline,將這個函數還原成普通函數,因此並不是說把一個函數定義爲inline函數就一定會被編譯器識別爲內聯函數,具體取決於編譯器的實現和函數體的大小。

四、內聯函數和宏定義的區別

       內聯函數和宏的區別在於,宏是由預處理器對宏進行替代,而內聯函數是通過編譯器控制來實現的。而且內聯函數是真正的函數,只是在需要用到的時候,內聯函數像宏一樣的展開,所以取消了函數的參數壓棧,減少了調用的開銷。你可以象調用函數一樣來調用內聯函數,而不必擔心會產生於處理宏的一些問題。內聯函數與帶參數的宏定義進行下比較,它們的代碼效率是一樣,但是內聯歡函數要優於宏定義,因爲內聯函數遵循的類型和作用域規則,它與一般函數更相近,在一些編譯器中,一旦關聯上內聯擴展,將與一般函數一樣進行調用,比較方便。 

       另外,宏定義在使用時只是簡單的文本替換,並沒有做嚴格的參數檢查,也就不能享受C++編譯器嚴格類型檢查的好處,另外它的返回值也不能被強制轉換爲可轉換的合適的類型,這樣,它的使用就存在着一系列的隱患和侷限性。

       C++的inline的提出就是爲了完全取代宏定義,因爲inline函數取消了宏定義的缺點,又很好地繼承了宏定義的優點,《Effective C++》中就提到了儘量使用Inline替代宏定義的條款,足以說明inline的作用之大。

五、使用注意事項

 1.內聯函數不能包括複雜的控制語句,如循環語句和switch語句;

 2.只將規模很小(一般5個語句一下)而使用頻繁的函數聲明爲內聯函數。在函數規模很小的情況下,函數調用的時間開銷可能相當於甚至超過執行函數本身的時間,把它定義爲內聯函數,可大大減少程序運行時間。

 

 參考博客

  https://www.cnblogs.com/msdn1433/p/3569176.html

  https://www.cnblogs.com/sherry-best/archive/2013/03/27/2984535.html

  https://www.cnblogs.com/develop-me/p/5678897.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章