inline 與 constexpr 函式


在呼叫函式時會有額外的資源負擔,一些小函式,可以「建議」編譯器設為 inline 行內,若建議被採納,該函式會自動在呼叫點展現為程式碼,因為編譯器需要其實作才能展開函式呼叫,inline 函式通常直接在標頭檔中實作,例如:

math.h

inline int pow2(int num) { 
    return num * num; 
} 

int pow(int, int);

配合標頭檔,可以如下實作 pow 函式本體:

math.cpp

#include "math.h"

int pow(int n, int p) {
    int r = 1; 

    for(int i = 0; i < p; i++) {
        r *= n;
    }

    return r; 
}

呼叫函式時不用任何改變,例如:

main.cpp

#include <iostream>
#include "math.h"
using namespace std;

int main() {
    int num = 0;
    int power = 0; 

    cout << "輸入數值:"; 
    cin >> num; 

    cout << "輸入次方:"; 
    cin >> power; 

    cout << num << " 平方:" << pow2(num) << endl
         << num << " 的 " << power << " 次方:" 
         << pow(num, power) 
         << endl; 

    return 0;
}

inline 函式只能建議編譯器,建議不一定被採納,例如遞迴函式無法在呼叫點展開,數千行的函式也不適合在呼叫點展開,如果編譯器拒絕將函式展開,會視為一般函式進行編譯,inline 的建議會被忽略。

如果函式夠簡單,簡單到編譯器可以推斷出傳回值,可以使用 constexpr 修飾,呼叫這類函式時,若能推斷出值,編譯器就會用值來取代呼叫,最簡單的情況就是:

constexpr double Pi() {
    return 3.14159;
}

然而,也可以是依參數計算的結果,例如:

constexpr int addOne(int n) {
    return n + 1;
}

在呼叫時若是:

constexpr int r = addOne(100);

若編譯器直接推斷的 101 會取代 addOne 呼叫,也就是 constexpr int r = 101 來進行編譯;使用 constexpr 修飾的函式,通常寫在標頭檔中。