1. 程式人生 > 實用技巧 >5 行內函數

5 行內函數

目錄

1 常量與巨集回顧

  • C++ 中的 const 常量可以替代巨集常數定義,如:

    const int A = 3;  <=> #define A 3
    
  • 問題:C++ 中是否有解決方案替代巨集程式碼片段

2 行內函數

  • C++ 中推薦使用行內函數替代巨集程式碼片段

  • C++ 中使用 inline 關鍵字宣告行內函數

    行內函數宣告時 inline 關鍵字必須和函式定義結合在一起,否則編譯器會直接忽略內聯請求

    inline int func(int a,int b)
    {
        return a < b ? a : b;
    }
    
  • C++ 編譯器可以將一個函式進行內聯編譯

  • 被 C++ 編譯器內聯編譯的函式叫做行內函數

  • C++ 編譯器直接將函式體插入函式呼叫的地方

  • 行內函數沒有普通函式呼叫時的額外開銷(壓棧,跳轉,返回)

  • C++ 編譯器不一定滿足函式的內聯請求

  • 行內函數示例1

    • Demo

      #include <stdio.h>
      
      //巨集程式碼塊
      #define FUNC(a, b) ((a) < (b) ? (a) : (b))
      
      //行內函數塊
      inline int func(int a, int b)
      {
          return a < b ? a : b;
      }
      
      int main(int argc, char *argv[])
      {
          int a1 = 1, a2 = 1;
          int b1 = 3, b2 = 3;
          int c1 = FUNC(++a1, b1);  //<=>int c = ((++a) < (b) ? (++a) : (b))
          int c2 = func(++a2, b2);
          
          printf("a1 = %d\n", a1);  //3
          printf("b1 = %d\n", b1);  //3
          printf("c1 = %d\n", c1);  //3
          
          printf("a2 = %d\n", a2);  //2
          printf("b2 = %d\n", b2);  //3
          printf("c2 = %d\n", c2);  //2
          
          return 0;
      }
      
  • 行內函數具有普通函式的特徵(引數檢查,返回型別等

  • 函式的內聯請求可能被編譯器拒絕

  • 函式被內聯編譯後,函式體直接擴充套件到呼叫的地方

  • 巨集程式碼片段由前處理器處理,進行簡單的文字替換,沒有任何編譯過程,因此可能出現副作用

  • 現代 C++ 編譯器能夠進行編譯優化,一些函式即使沒有 inline 宣告,也可能被內聯編譯

  • 一些現代 C++ 編譯器提供了擴充套件語法,能夠對函式進行強制內聯,如:

    //g++
    __attribute__((always_inline))屬性
    //MSVC
    __forceinline
    
  • 行內函數示例2

    • Demo

      #include <stdio.h>
      
      //__forceinline
      //__attribute__((always_inline))
      //inline 
      int add_inline(int n);
      
      int main(int argc, char *argv[])
      {
          int r = add_inline(10);
      
          printf(" r = %d\n", r);
      
          return 0;
      }
      
      inline int add_inline(int n)
      {
          int ret = 0;
      
          for(int i=0; i<n; i++)
          {
              ret += i;
          }
      
          return ret;
      }
      

3 注意事項

  • C++ 中 inline 內聯編譯的限制
    • 不能存在任何形式的迴圈語句
    • 不能存在過多的條件判斷語句
    • 函式體不能過於龐大
    • 不能對函式進行取址操作
    • 函式內聯宣告必須在呼叫語句之前