C++基礎系列——內聯函數


1. 為什么設計內聯函數

函數調用是有時間和空間開銷的:調用一個函數之前通常要將實參、局部變量、返回地址以及若干寄存器都壓入棧中,然后才能執行函數體中的代碼,函數體中的代碼執行完畢后還要恢復。

為了消除函數調用的時空開銷,C++ 提供一種提高效率的方法,即在編譯時將函數調用處用函數體替換,這種在函數調用處直接嵌入函數體的函數稱為內聯函數(Inline Function)。內聯函數可以避免函數調用開銷

2. 定義內聯函數

指定內聯函數的方法很簡單,只需要在函數定義處增加 inline 關鍵字

void swap(int *, int *);    // 函數原型,也可以添加 inline,但編譯器會忽略

int main(){
    int m = 10;
    int n = 11;
    swap(&m, &n);   //編譯器可能會將函數代碼直接嵌入此處
}

inline void swap(int *a, int *b){
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

注意:要在函數定義處添加 inline 關鍵字**

由於內聯函數比較短小,我們通常的做法是省略函數原型,將整個函數定義(包括函數頭和函數體)放在本應該提供函數原型的地方。

inline void swap(int *a, int *b){
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

int main(){
    int m = 10;
    int n = 11;
    swap(&m, &n);   //編譯器可能會將函數代碼直接嵌入此處
}

對函數作 inline 聲明只是對編譯器提出的一個建議,不是強制性的,並非一經指定為 inline 編譯器就必須這樣做。編譯器會根據具體情況決定是否這樣做。

3. 內聯函數代替宏

宏是可以帶參數的,它在形式上和函數非常相似。不過不像函數,宏僅僅是字符串替換,不是按值傳遞,所以在編寫宏時要特別注意,一不小心可能就會踩坑。如下所示:

#include <iostream>

using namespace std;

#define SQ(y) y *y
#define SQ2(y) (y)*(y)
#define SQ3(y) ((y)*(y))

int main()
{
    int n = 10; 
    int sq = SQ(n); // 此時宏調用沒問題
    int sq2 = SQ(n+1);  // 結果錯的:n + 1 * n + 1,可以改進成 SQ2 的形式
    int sq3 = 200 / SQ2(n)  // 200 / 10 * 10,結果錯的,此時可以改進成 SQ3 的形式
    cout << sq << endl;
    return 0;
}

宏定義是一項“細思極密”的工作,一不小心就會踩坑,而且不一定在編譯和運行時發現,給程序埋下隱患。

可以將宏換位內聯函數。

#include <iostream>

using namespace std;

inline int SQ(int y) { return y * y; }

int main()
{
    int n, sq;
    cin >> n;

    sq = SQ(n);
    cout << sq << endl;

    sq = SQ(n + 1);
    cout << sq << endl;

    sq = 200 / SQ(n + 1);
    cout << sq << endl;
    return 0;
}

和宏一樣,內聯函數可以定義在頭文件中,並且頭文件被多次#include后也不會引發重復定義錯誤。這一點和非內聯函數不同,非內聯函數是禁止定義在頭文件中的,它所在的頭文件被多次#include后會引發重復定義錯誤。

可以看到內聯函數主要有兩個作用,一是消除函數調用時的開銷,二是取代帶參數的宏。

4. 如何規范地使用 C++內聯函數

  • inline 在函數聲明處是無效的,編譯器會忽略函數聲明處的 inline 關鍵字。

  • 內聯函數不應該有聲明,應該將函數定義放在本應該出現函數聲明的地方,這是一種良好的編程風格。

  • 內聯函數在編譯時會將函數調用處用函數體替換,編譯完成后函數就不存在了。如果將內聯函數的聲明放在頭文件中,定義放在源文件中,這時會出錯,能正常編譯,但無法鏈接。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM