行內函數
關鍵字inline,inline是空間換時間,提高了程式效率但花費了更多空間。舉個例子,下面是一段C語言程式碼:
void fun(int i)
{
return i*2;
}
int main()
{
int a = 4;
int b = fun(a);
}
假定以上C檔案被編譯器編譯成的彙編程式碼如下:
_f_int:
add ax,@sp[-8] ;相當於ax = ax + 4
ret
_main:
add sp,#8 ;堆疊指標SP移動8個位元組,空出來的8個位元組分別存放a,b
mov ax,#4 ;將立即數4送往暫存器ax中
mov @sp[-8],ax ;將ax的值送往堆疊指標-8個位元組的記憶體單元中,可以看做a = 4這一操作
mov ax,@sp[-8] ;將a的值賦值給ax
push ax ;將暫存器的內容壓入棧中
call _f_int ;call會做兩件事,先把下一條指令的地址壓入棧中,再跳轉到要執行的子程式
mov @sp[-4],ax ;將ax的值賦值給b
pop ax ;將函式中的臨時變數i出棧
函式呼叫需要做如下事情:將函式引數壓入棧中、將返回地址壓入棧中、準備返回值、將所有以上入棧的內容出棧。為了提高效率,設定關鍵字inline告訴編譯器這個一個宣告而非定義,在呼叫這個被inline修飾的函式時會將程式碼直接嵌入到呼叫的地方。有點類似於宏定義,宏定義是在編譯前對所有的內容進行替換不涉及型別檢查,而內涵函式存在型別檢查。行內函數經過編譯不會生成obj檔案。
透過加了inline關鍵字的函式編譯後結果:
可以看到彙編程式碼不會執行部分入棧和出棧操作,從而提高了程式的效率。
普通函式與行內函數:
普通函式時透過跳轉到函式體裡面執行程式,會有一些入棧出棧等操作;行內函數就是將程式碼嵌入呼叫該函式的位置,每呼叫一次就嵌入一次,因此提高了程式執行效率但增大了記憶體空間,所以說是空間換時間的策略
通常在程式設計時要求.h檔案存放函式宣告,.cpp檔案對函式進行定義。
//a.h
inline void f(int i, int j);
//a.cpp
#include "a.h"
void f(int i, int j)
{
cout << i << "," << j << endl;
}
//main.cpp
int main()
{
f(10,10);
return 0;
}
執行以上程式碼會出錯:
解決方法:不需要a.cpp檔案,將f行內函數的定義放在標頭檔案中。
<br>
//a.h
#include <iostream>
using namespace std;
inline void f(int i, int j)
{
cout << i << "," << j << endl;
}
//main.cpp
#include "a.h"
int main()
{
f(10,10);
return 0;
}
結果:
總結:
1.行內函數採取的是空間換時間的策略。
2.通常函式程式碼只有2~3行或者是被重複呼叫的函式,可以新增inline關鍵字。
3.某些情況即使新增了inline,如果程式佔用空間過大,編譯器也不會將該函式看做是行內函數
參考:
浙江大學翁凱C++
C++ Primer Plus 第8章