inline內聯函數話題
/*
*運行平臺:Visual Studio 2015
*參考資料:《C++ Primer Plus(第6版)》,傳智掃地增C++基礎課程
*/
目錄
一、前言
在講inline內聯函數之前,先問大家一個
問題:C++中的const常量可以在一定程度上替代宏常數定義,那麼是否有解決方案替代宏代碼片段呢?
回答:肯定有的,畢竟C++是對C的升級嘛,C++中推薦使用內聯函數替代宏代碼片段。
二:那麼怎麼使用呢?
在C++中使用inline關鍵字聲明內聯函數,聲明時inline關鍵字必須和函數定義結合在一起,否則編譯器會直接忽略內聯請求。如:inline void get();
三、注意
1、內聯函數生成的代碼中是沒有定義的
C++編譯器直接將函數體插入在函數調用的地方 ,內聯函數沒有普通函數調用時的額外開銷(壓棧,跳轉,返回)。
因此,當函數體的執行開銷遠大於壓棧,跳轉和返回所用的開銷時,那麼內聯將無意義。
inline void get()
{
printf("Hello\n");
}
int main()
{
get();
/* 相當於 */
{
printf("Hello\n");
}
}
2、C++編譯器不一定準許函數的內聯請求
內聯函數是一種特殊的函數,具有普通函數的特徵(參數檢查,返回類型等)。內聯函數是對編譯器的一種請求,既然是請求,那麼肯定可以拒絕,因此編譯器可能拒絕這種請求。
3、inline與宏代碼片段區別
內聯函數由編譯器處理,直接將編譯後的函數體插入調用的地方。
宏代碼片段由預處理器處理, 進行簡單的文本替換,沒有任何編譯過程。
4、C++編譯器能夠進行編譯優化
現代C++編譯器能夠進行編譯優化,因此一些函數即使沒有inline聲明,也可能被編譯器內聯編譯。
5、C++中內聯編譯的限制
- 不能存在任何形式的循環語句
- 不能存在過多的條件判斷語句
- 函數體不能過於龐大
- 不能對函數進行取址操作
- 函數內聯聲明必須在調用語句之前
6、inline替代宏代碼片段就可以避免宏的副作用
用一段程序來說明:
#include "iostream"
using namespace std;
#define MYFUNC(a, b) ((a) < (b) ? (a) : (b))
inline int myfunc(int a, int b)
{
return a < b ? a : b;
}
int main()
{
int a = 1;
int b = 3;
int c = myfunc(++a, b);
printf("a = %d\n", a);
printf("b = %d\n", b);
printf("c = %d\n", c);
c = MYFUNC(++a, b);
printf("a = %d\n", a);
printf("b = %d\n", b);
printf("c = %d\n", c);
system("pause");
return 0;
}
結果:可以看到兩者執行的結果不一致,因此使用#define定義代碼塊時可能會造成一定的副作用。
解釋:
結論:
- 內聯函數在編譯時直接將函數體插入函數調用的地方。
- inline只是一種請求,編譯器不一定允許這種請求。
- 內聯函數省去了普通函數調用時壓棧,跳轉和返回的開銷。