inline函數學習筆記

一、c++ inline函數產生原因

由於函數調用會有一定的時間和空間方面的開銷,特別是對於一些函數體代碼不大但又被頻繁調用的函數來講,效率是很低的。

在C語言中,可以用宏函數來提高上面那種情況的效率,但宏函數有些缺點,它只是提供一個文本替換的功能,而不是一個真正的函數。所以在C++中引入了inline函數來解決這個問題,它會像宏函數一樣在調用函數處用內聯函數體的代碼進行替換,還遵循函數的類型和作用域規則,所以它能像一般的函數那樣進行調用和調試。

二、如何定義inline函數

inline函數只有和函數體定義放在一起是纔有效,所以如果像這樣聲明一個內聯函數

  1. inline void Func(); 

那麼在編譯器看來,它與普通函數沒有兩樣,如下所示

  1. inline void Func()  
  2. {  
  3. // ...  

這樣它才具有比一般函數更快的執行能力。

還有一種定義方式是在類內部定義的函數。在c++中,如果在類內部定義了函數體的函數,則默認其爲內聯,而不管是否有inline關鍵字。所以像如下兩個函數Func1、Func2都屬於內聯。

  1. class A  
  2. {  
  3. public:  
  4.     inline void Fun1(){ //... }  
  5.     void Fun2(){ //... }  

當然,內聯函數並不是萬能的,在某些情況下,它不僅不能像期望的那樣提升性能,甚至會起反作用。inline只是對編譯器的一種提示,而不是命令。也就是說,只要編譯器願意,它就可以隨意地忽略掉你的指令,當編譯器遇到內聯函數時,就會針對函數體的上下文進行優化,以確定是否執行內聯。如果編譯器認爲當前的函數過於複雜、函數體過大,或者這個函數是虛函數,就會拒絕將其內聯,這取決與編譯器,不同編譯器處理方式不一樣。

三、在使用inline時,需注意如下幾點:

1、在inline函數內不允許用循環語句和開關語句,函數體不能過於複雜;

2、對於內存空間有限的機器而言,慎用內聯。過分使用內聯會造成函數代碼過於膨脹,會佔用太多空間;

3、不能對構造或者析構函數進行內聯,儘管它們看似很簡短。對於這一點看下面這個類Derived的構造函數:

  1. class Base  
  2. {  
  3. public:  
  4.     ...  
  5. private:  
  6.     string s1, s2;  
  7. };  
  8.  
  9. class Derived: public Base  
  10. {  
  11. public:  
  12.     Derived(){}  
  13.     ...  
  14. private s3, s4, s5;  
  15. }; 

這個構造函數看起來的確是個內聯的好材料,因爲它沒有代碼,實際上,它含有相當多的代碼。對於上面這個空的Derived的構造函數,有些編譯器會爲它產生相當於下面的代碼:

  1. // 一個Derived構造函數的可能的實現  
  2. Derived::Derived()  
  3. {  
  4.     // 如果在堆上創建對象,爲其分配堆內存  
  5.     if (本對象在堆上)  
  6.     {  
  7.         this = ::operator new(sizeof(Derived));  
  8.     }  
  9.     // 初始化父類對象  
  10.     Base::Base();  
  11.     s3.string();    // 構造s3  
  12.     s4.string();    // 構造s4  
  13.     s5.string();    // 構造s5  

如果string的構造函數也恰巧被內聯,Derived的構造函數將得到其代碼的5個拷貝(2個繼承而來,3個自己聲明)。現在你應該明白,內聯Derived的構造函數並非可以很簡單就決定的;類似的情況也適用於析構。

4、內聯函數只適合於只有1~5行的小函數。

四、內聯還得面臨2個頭疼的問題

第一,該如何維護?一個函數開始的時候可能滿足了設定的內聯標準,並以內聯的形式出現,但隨着系統的擴展升級,函數體中增添了一些新功能,函數體變得複雜了,這就使內聯函數不再適合內聯,此時需要把函數前面的inline去掉,並把函數體放到相應的源文件中,這會使維護的難度有所增加。

第二,不可避免的重新編譯。當內聯函數實現改變的時候,用戶必須重新編譯他們的代碼以反映出這種改變。而對於非內聯函數,我們僅僅需要重新鏈接。

所以,使用inline需要依靠積累的經驗來進行判斷,合理正確的使用內聯,可以提高程序的性能,反之,會帶來意想不到的副作用!

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