1. 程式人生 > >第6課-行內函數分析

第6課-行內函數分析

一、常量與巨集回顧

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

const int A = 3;  // #define A 3

二、行內函數

  • C++中推薦使用行內函數替代巨集程式碼片段
  • C++中使用inline關鍵字宣告行內函數
inline int func(int a,int b){
  return a < b? a : b;
}

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

  • C++編譯器可以將一個函式進行內聯編譯
  • 被C++編譯器內聯編譯的函式叫做行內函數
  • C++編譯器直接將函式體插入函式呼叫的地方
  • 行內函數沒有普通函式呼叫時的額外開銷(壓棧,跳轉,返回)

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

程式設計實驗:行內函數初探

#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 a = 1;
    int b = 3;
    int c = FUNC(++a, b);

    printf
("a = %d\n", a); printf("b = %d\n", b); printf("c = %d\n", c); return 0; }

列印結果:

3
3
3

務必理解巨集定義的效果,是在使用位置直接替換

  • 行內函數具有普通函式的特徵(引數檢查返回型別等)
  • 函式的內聯請求可能被編譯器拒絕
  • 函式被內聯編譯後,函式體直接擴充套件到呼叫的地方

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

  • 現代C++編譯器能夠進行編譯優化,一些函式即使沒有inline宣告,也可能被內聯編譯
  • 一些現代C++編譯器提供了擴充套件語法,能夠對函式進行強制內聯,如:
    • g++:__attribute__((always_line))屬性
    • MSVC:_forceinline

程式設計實驗:行內函數深度示例

#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;
}

列印結果:r = 45

注意事項:

C++中inline內聯編譯的限制:

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

三、總結

  • C++中可以通過inline宣告行內函數
  • 編譯器直接將行內函數體擴充套件到函式呼叫的地方
  • inline只是一種請求,編譯器不一定允許這種請求
  • 行內函數省去了函式呼叫時壓棧,跳轉和返回的開銷