代碼的重複導致臃腫的執行程序,一直讓很多程序員不勝其煩,而內聯函數提供了另一種選擇。編譯器將使用相應的函數代碼替換函數調用。因此,內聯函數的運行速度比常規函數稍快,但代價是需要佔用更多內存。

1 .內聯函數的使用

在函數聲明前加上關鍵字inline;

在函數定義前加上關鍵字inline。

示例如下:


#include
inline double square(double x){return x*x;}
int main()
{
using namespace std;
double a,b;
double c = 13.0;
a = square(5.0);
b = square(4.5+7.5);
cout<<<
cout<<
cout<<
cout<<
return 0;
}
}
程序輸出結果如下:
a=25,b=144
c=13
c square=169
now c=14

增加了 inline 關鍵字的函數稱爲“內聯函數”。內聯函數和普通函數的區別在於:當編譯器處理調用內聯函數的語句時,不會將該語句編譯成函數調用的指令,而是直接將整個函數體的代碼插人調用語句處,就像整個函數體在調用處被重寫了一遍一樣。

inline適用的函數有兩種,一種是在類內定義的成員函數,另一種是在類內聲明,類外定義的成員函數,對於這兩種情況inline的使用有一些不同:

(1)類內定義成員函數

這種情況下,我們可以不用在函數頭部加inline關鍵字,因爲編譯器會自動將類內定義的函數聲明爲內聯函數,代碼如下:

class temp{

public:

int amount;

//構造函數

temp(int amount){

this->amount = amount;

}

//普通成員函數,在類內定義時前面可以不加inline

void print_amount(){

cout << this-> amount;

}

}


從上面的代碼可以看出,在類內定義函數時,可以不加inline關鍵字,編譯器會自動將類內定義的函數(構造函數、析構函數、普通成員函數等)設置爲內聯,具有內聯函數調用的性質。

(2) 類內聲明函數,在類外定義函數

根據C++編譯器的規則,這種情況下如果想將該函數設置爲內聯函數,則可以在類內聲明時不加inline關鍵字,而在類外定義函數時加上inline關鍵字,代碼如下所示:

class temp{

public:

int amount;

//構造函數

temp(int amount){

this->amount = am

ount;

}

//普通成員函數,在類內聲明時前面可以不加inline

void print_amount()

}

//在類外定義函數體,必須在前面加上inline關鍵字

inline void temp:: print_amount(){

cout << amount << endl;

}

從上面代碼我們可以看出,類內聲明可以不用加上inline關鍵字,但是類外定義函數體時必須要加上,這樣才能保證編譯器能夠識別其爲內聯函數。

另外,我們可以在聲明函數和定義函數的同時寫inline,也可以只在函數聲明時加inline,而定義函數時不加inline。只要在調用該函數之前把inline的信息告知編譯系統,編譯系統就會在處理函數調用時按內聯函數處理。也就是說,上面說的幾種方法都可以實現一個內聯函數的定義,根據自己的需要來寫即可。

2 .內聯函數與宏定義的區別

C語言使用預處理器語句#define來提供宏。如下例所示:

#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,卻仍遞增了兩次。

因此,宏定義和內聯函數存在本質的區別,轉換的時候應考慮是否轉換後功能是否正常。

3什麼時候使用內聯函數

如果執行函數代碼的時間比處理函數調用機制的時間長,則節省的時間佔比很小。若代碼執行時間很短,則內聯函數就可以節省函數調用的時間。

Tips

^當函數體比較小的時候, 內聯該函數可以令目標代碼更加高效. 對於存取函數以及其它函數體比較短, 性能關鍵的函數, 鼓勵使用內聯.

^但濫用內聯將導致程序變慢. 內聯可能使目標代碼量或增或減, 這取決於內聯函數的大小. 內聯非常短小的存取函數通常會減少代碼大小, 但內聯一個相當大的函數將戲劇性的增加代碼大小. 現代處理器由於更好的利用了指令緩存, 小巧的代碼往往執行更快。

^ 結論: 一個較爲合理的經驗準則是, 不要內聯超過 10 行的函數. 謹慎對待析構函數, 析構函數往往比其表面看起來要更長, 因爲有隱含的成員和基類析構函數被調用!

^另一個實用的經驗準則: 內聯那些包含循環或 switch 語句的函數常常是得不償失 (除非在大多數情況下, 這些循環或 switch 語句從不被執行).有些函數即使聲明爲內聯的也不一定會被編譯器內聯, 這點很重要; 比如虛函數和遞歸函數就不會被正常內聯. 通常, 遞歸函數不應該聲明成內聯函數.(遞歸調用堆棧的展開並不像循環那麼簡單, 比如遞歸層數在編譯時可能是未知的, 大多數編譯器都不支持內聯遞歸函數). 虛函數內聯的主要原因則是想把它的函數體放在類定義內, 爲了圖個方便, 抑或是當作文檔描述其行爲, 比如精短的存取函數.

相關文章