[C++] 內聯函數vs預處理器宏


Answers

首先,編譯前的預處理器宏只是代碼中的“複製粘貼”。 所以沒有類型檢查 ,可能會出現一些副作用

例如,如果你想比較2個值:

#define max(a,b) ((a<b)?b:a)

例如,如果使用max(a++,b++) ,則會出現副作用( ab將遞增兩次)。 相反,使用(例如)

inline int max( int a, int b) { return ((a<b)?b:a); }
Question

內聯函數與預處理器宏有什麼不同?




在海灣合作委員會(我不確定其他人),聲明一個函數內聯,只是提示編譯器。 編譯器在一天結束時仍然決定是否在被調用時包含函數的主體。

內聯函數和預處理器宏之間的區別比較大。 預處理器宏只是在一天結束時的文本替換。 你放棄了編譯器對參數和返回類型進行類型檢查的能力。 對參數的評估是非常不同的(如果你傳遞給函數的表達式有副作用,那麼調試的時候就會有一個非常有趣的時間)。 函數和宏的使用位置有細微的差別。 例如,如果我有:

#define MACRO_FUNC(X) ...

MACRO_FUNC顯然定義了函數的主體。 需要特別注意,以便在所有情況下都可以正常運行,例如,寫得不好的MACRO_FUNC會導致錯誤

if(MACRO_FUNC(y)) {
 ...body
}

一個正常的功能可以用在那裡沒有問題。




關鍵的區別是類型檢查。 編譯器將檢查你作為輸入值傳遞的是可以傳遞給函數的類型。 對於預處理器宏來說,情況並非如此 - 在進行任何類型檢查之前,這些宏都會被擴展,並且會導致嚴重且難以檢測到的錯誤。

這裡還有其他幾個不太明顯的要點。




宏忽略名稱空間。 這使他們變得邪惡。




如果內聯函數中存在任何迭代或遞歸語句,則內聯函數將作為函數調用行為,以防止重複執行指令。 這對於保存程序的整體內存非常有幫助。




內聯函數將維護數值語​​義,而預處理器宏只是複制語法。 如果你多次使用參數,你可以用預處理宏得到非常微妙的錯誤 - 例如,如果參數包含像“i ++”這樣的執行兩次的突變是一個驚喜。 內聯函數不會有這個問題。