文章目錄
-
- 1 内聯函數
- 2 深入内聯函數
- 3 小結
C++ 中的 const 常量可以替代宏常數定義,那麼 C++ 中是否有解決方案替代代碼片呢?
- C++ 中使用 inline 關鍵字聲明内聯函數,推薦使用内聯函數代替宏代碼片段

- C++ 編譯器直接将内聯函數體插入函數調用的地方
- 内聯函數沒有普通函數調用時的額外開銷(壓棧,跳轉,傳回)
- C++ 編譯器不一定滿足函數的内聯請求
執行個體分析:内聯函數初探
// 4-1.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;
}
代碼很簡單,就是求兩數的最小值,編譯運作:
$ g++ 4-1.c -o 4-1
$ ./4-1
a = 2
b = 3
c = 2
将第 12 行改為 int c = FUNC(++a, b); 再次編譯運作:
$ g++ 4-1.c -o 4-1
$ ./4-1
a = 3
b = 3
c = 3
為什麼會出現這種情況呢,因為宏定義是直接展開,展開後如下:
int c = ((++a) < (b) ? (++a) : (b));
是以 ++a 操作計算了兩次,a,b,c 的值都是 3。
- 用 VS2013 反彙編,如下圖所示
可以看出,雖然函數 func() 聲明為 inline,但是這裡并沒有展開,還是進行了函數調用。inline 隻是一個請求,C++ 編譯器不一定滿足内聯請求。
- 内聯函數具有普通函數的特性(參數檢查,傳回類型等)
- 函數的内聯請求可能被編譯器拒絕
- 函數被内聯函數編譯器後,函數體直接擴充到調用的地方
- 宏代碼片由預處理器處理,進行簡單的文本替換,沒有任何編譯過程
- 現代 C++ 編譯器能夠進行編譯優化,一些函數即使沒有 inline 聲明,也可能被内聯編譯
- 一些現代 C++ 編譯器擴充了文法,能夠對函數進行強制内聯,如:
- g++: __attribute__((always_inline))
- 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;
}
上面的代碼中 inline 是 C++ 中的标準,向編譯器申請将函數設為内聯函數,編譯器不一定滿足内斂要求;__forceinline 是 vs 編譯器的強制内聯标示符,将 inline 換為__forceinline,強制函數為内聯類型;
__attribute__((always_inline)) 是 g++ 編譯器的标示符,将 inline 換為__attribute__ 強制函數為内聯類型。
- 不能存在任何形式的循環語句
- 不能存在過多的條件判斷語句
- 函數體不能過于龐大
- 不能對函數進行取址操作
- 函數内聯聲明必須在調用語句之前