1. 程式人生 > >C++中的行內函數(inline)與巨集定義

C++中的行內函數(inline)與巨集定義

為什麼要使用行內函數呢?

當我們定義完一個函式之後,實際呼叫的時候,函式體本身會壓入堆疊,主函式再從堆疊裡面把這部分內容提取出來,產生一定的系統開銷,對於大型函式來說,這部分開銷可能相對於函式體本身執行的開銷來說微乎其微。但是如果一個函式僅僅只是為了完成一個特別簡單的功能,比如交換兩個變數的值,亦或是求兩個變數的最大值,這時,呼叫函式的開銷,可能就會大於函式體執行本身了。作為一個追求高效能的程式而言,大量的這種函式呼叫的堆積,勢必會使得整體的效能下降。

例如,下面這個返回a和b最大值的函式,

#include<iostream>
using namespace std;

int max(int a,int b) {
	return a > b? a:b;
}

int main() {
	int a = 3;
	int b = 5;
	cout<<max(a,b)<<endl;
}

如果換成行內函數,就在函式定義的時候,前面加上inline即可,然後主函式執行的時候,相當於載入了函式體的內容:

#include<iostream>
using namespace std;

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

int main() {
	int a = 3;
	int b = 5;
	cout<<max(a,b)<<endl; 
	//相當於 cout<<(a>b?a:b)<<endl;
}

從而減小了把max寫成函式的系統額外開銷。本質上是一種犧牲空間複雜度換取時間複雜度的過程。

但是需要注意的是,行內函數不可以直接用於沒有定義的函式宣告。此外,在面向物件程式設計中,定義在類內的成員函式預設定義為行內函數。可以使用所在類的保護成員和私有成員。

行內函數與巨集定義的區別:

巨集定義具有兩個缺點:一是不能除錯,二是隻是進行了簡單的文字替換,如果重複使用的話,可能會出現重定義的情況。而與之相比的話,行內函數就很靈活了。下面的這個例子很生動,

#define SQUARE(X) X*X

巨集定義時通過文字替換開實現的--X是引數的符號標記。

a = square(5.0);   //->a=5.0*5.0;
b = square(4.5+7.5); //->b=4.5+7.5*4.5+7.5
d = square(c++);  //->d=c++*c++

可以看出,對於b,需要使用括號才能正常運算。

#define SQUARE(X) ((X)*(X))

對於c,卻仍遞增了兩次。 因此,巨集定義和行內函數存在本質的區別,轉換的時候應考慮是否轉換後功能是否正常。