C++ inline

一:inline定義與使用html

         inline 關鍵字用來定義一個類的內聯函數,引入它的主要緣由是用它替代C中表達式形式的宏定義。安全

表達式形式的宏定義一例:函數

   #define ExpressionName(Var1,Var2) ((Var1)+(Var2))*((Var1)-(Var2))爲何要取代這種形式呢,且聽我道來:
     1. 首先談一下在C中使用這種形式宏定義的緣由,C語言是一個效率很高的語言,這種宏定義在形式及使用上像一個函數,但它使用預處理器實現,沒有了參數壓棧,代碼生成 等一系列的操做,所以,效率很高,這是它在C中被使用的一個主要緣由。
  2. 這種宏定義在形式上相似於一個函數,但在使用它時,僅僅只是作預處理器符號表中的簡單替換,所以它不能進行參數有效性的檢測,也就不能享受C++ 編譯器 嚴格類型檢查的好處,另外它的返回值也不能被強制轉換爲可轉換的合適的類型,這樣,它的使用就存在着一系列的隱患和侷限性。
      3. 在C++中引入了類及類的訪問控制,這樣,若是一個操做或者說一個表達式涉及到類的保護成員或私有成員,你就不可能使用這種宏定義來實現(由於沒法將this指針放在合適的位置)。
       4. inline 推出的目的,也正是爲了取代這種表達式形式的宏定義,它消除了它的缺點,同時又很好地繼承了它的優勢。

2、爲何inline能很好地取代預約義呢?

  對應於上面的1-3點,闡述以下:性能

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

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

 3. inline 能夠做爲某個 類的成員函數 ,固然就能夠在其中使用所在類的保護成員及私有成員。
在什麼時候使用inline函數:
   首先,你可使用inline函數徹底取表明達式形式的宏定義。
    另外要注意,內聯函數通常只會用在函數內容很是簡單的時候,這是由於,內聯函數的代碼會在任何調用它的地方展開,若是函數太複雜,代碼膨脹帶來的惡果極可能會大於效率的提升帶來的益處。內聯函數最重要的使用地方是用於類的存取函數。

三如何使用類的inline函數:

  簡單提一下inline 的使用吧: .net

  1.在類中定義這種函數:指針

  class ClassName{調試

   .....
   ....

  INT GetWidth(){return m_lPicWidth;}; // 若是在類中直接定義,不須要用inline修飾,編譯器自動化爲內聯函數htm

  .... //此說法在《C++ Primer》中說起

  .... 

  }

 2.在類外定義前加inline關鍵字:

  class Account {

  public:

  Account(double initial_balance) { balance = initial_balance; } //與1相同

  double GetBalance(); //在類中聲明

  double Deposit( double Amount );

  double Withdraw( double Amount );

  private:

  double balance;

  };

  inline double Account::GetBalance() { return balance; } //在類外定義時添加inline關鍵字 

  inline double Account::Deposit( double Amount ) { return ( balance += Amount ); }

  inline double Account::Withdraw( double Amount ) { return ( balance -= Amount ); } 

  此外含有一些規則需注意:

  一、inline說明對編譯器來講只是一種建議,編譯器能夠選擇忽略這個建議。好比,你將一個長達1000多行的函數指定爲inline,編譯器就會忽略這個inline,將這個函數還原成普通函數。

  二、在調用內聯函數時,要保證內聯函數的定義讓編譯器"看"到,也就是說內聯函數的定義要在頭文件中,這與一般的函數定義不同。但若是你習慣將函數定義放在CPP文件中,或者想讓頭文件更簡潔一點,可這樣作:

  //SomeInline.h中

  #ifndef SOMEINLINE_H

  #define SOMEINLINE_H

  inline Type Example(void);

  //........其餘函數的聲明

  #include「SomeInlie.cpp」 //源文件後綴名隨編譯器而定

  #endif

  //SomeInline.cpp中

  #include"SomeInline.h"

   Type Example(void) 

  {

  //.......... 

  }

  //...............其餘函數的定義

  以上方法是通用、有效的,可放心使用,沒必要擔憂在頭文件包含CPP文件會致使編譯錯誤。

注意點:

      內聯函數既可以去除函數調用所帶來的效率負擔又可以保留通常函數的優勢。然而,內聯函數並非萬能藥,在一些狀況下,它甚至可以下降程序的性能。所以在使用的時候應該慎重。   
     1.咱們先來看看內聯函數給咱們帶來的好處:從一個用戶的角度來看,內聯函數看起來和普通函數同樣, 它能夠有參數和返回值,也能夠有本身的做用域,然而它卻不會引入通常函數調用所帶來的負擔。另外, 它能夠比宏更安全更容易調試。   
    固然有一點應該意識到,inline   specifier僅僅是對編譯器的建議,編譯器有權利忽略這個建議。那麼編譯器是如何決定函數內聯與否呢?通常狀況下關鍵性因素包括函數體的大小,是否有局部對象被聲明,函數的複雜性等等。   
     2.那麼若是一個函數被聲明爲inline可是卻沒有被內聯將會發生什麼呢?理論上,當編譯器拒絕內聯一個   函數的時候,那個函數會像普通函數同樣被對待,可是還會出現一些其餘的問題。

如下狀況不宜使用內聯:

  (1)若是函數體內的代碼比較長,使用內聯將致使內存消耗代價較高。

  (2)若是函數體內出現循環,那麼執行函數體內代碼的時間要比函數調用的開銷大。類的構造函數和析構函數容易讓人誤解成使用內聯更有效。要小心構造函數和析構函數可能會隱藏一些行爲,如「偷偷地」執行了基類或成員對象的構造函數和析構函數。因此不要隨便地將構造函數和析構函數的定義體放在類聲明中。一個好的編譯器將會根據函數的定義體,自動地取消不值得的內聯(這進一步說明了 inline 不該該出如今函數的聲明中)。

    參考:http://blog.csdn.net/zhangchao3322218/article/details/8099747

            http://www.cnblogs.com/berry/articles/1582702.html

相關文章
相關標籤/搜索