天天看點

C++基礎---内聯函數1. 内聯函數

1. 内聯函數

1.1 内聯函數的定義

  • 内聯函數:指用inline關鍵字修飾的函數;
  • 内聯函數:在類内定義的函數被預設成内聯函數;
  • 内聯函數:不是在調用時發生控制轉移,而是在編譯時将函數體嵌入在每一個調用處,編譯時,類似宏替換,使用函數體替換調用處的函數名;
  • 内聯函數的作用:内聯擴充是用來消除函數調用時的時間開銷。它通常用于頻繁執行的函數。 一個小記憶體空間的函數非常受益。

    注:一般在代碼中用inline修飾,但是能否形成内聯函數,需要看編譯器對該函數定義的具體處理。影響性能的一個重要因素是内聯技巧。

1.2 内聯函數的使用注意

  • 遞歸函數不能定義為内聯函數;
  • 内聯函數一般适合于不存在while和switch等複雜的結構,而且隻有1~5條語句的小函數上,否則編譯系統将該函數視為普通函數;
  • 内聯函數隻能先定義後使用,否則編譯系統也會把它認為是普通函數;
  • 對内聯函數不能進行異常的接口聲明;

1.3 内聯函數與宏比較

  • 内聯函數的功能和預處理宏的功能相似。
  • 宏的優缺點:

    優點:宏隻是在預處理的地方把代碼展開,不需要額外的空間和時間方面的開銷,是以調用一個宏比調用一個函數更有效率;

    缺點:宏不能通路對象的私有成員,宏的定義很容易産生二義性;

  • 内聯函數與宏的差別:

    宏是由預處理器對宏進行替代。

    内聯函數是通過編譯器控制來實作的;

    内聯函數是真正的函數,隻是在需要用到的時候,内聯函數像宏一樣的展開,是以取消了函數的參數壓棧,減少了調用的開銷;

1.4 内聯函數的性能測試

  • 可以做一個實驗,讓主函數分别調用内聯函數和非内聯函數,由于調用一次函數的開銷實在太小,隻有幾個機器指令,甚至還有機器硬體專設的機構幫忙,是以,為了看清内聯函數與非内聯函數的差别,可以分布調用10億次函數來放大時間差。
    #include <iostream> 
    
    
    #include <time.h>
    
    using namespace std;
    
    class A
    {
    public:
        int calc1(int a, int b);
    };
    int A::calc1(int a, int b)
    {
        return a+b;
    }
    
    class B
    {
    public:
        inline int calc2(int a, int b)//或 int calc2(int a, int b)
        {
            return a+b;
        }
    };
    
    int main()
    {
        A a;
        B b;
        int x[], y[], z[];
        clock_t t = clock();
        for(int i=; i<; i++)
        {
            for(int j=; j<; j++)
            {
                for(int k=; k<; k++)
                {
                    z[i] = a.calc1(x[j], y[k]);
                }
            }
        }
        cout<<"Not using inline:"<<(clock()-t)/CLK_TCK<<"seconds"<<endl;
    
        t = clock();
        for(int i=; i<; i++)
        {
            for(int j=; j<; j++)
            {
                for(int k=; k<; k++)
                {
                    z[i] = b.calc2(x[j], y[k]);
                }
            }
        }
        cout<<"Using inline:"<<(clock()-t)/CLK_TCK<<"seconds"<<endl;
        system("pause");
    
        return ;
    }
    =>Not using inline: seconds
      Using inline: seconds
    (本人用的是Visual Studio ,作業系統是Windows  位           ,硬碟是希捷 ST500LT012-DG142)
               
    注:實際測試内聯函數并非想象中的高速。

1.5 内聯函數的優缺點

  • 優點:是提高運作時間效率。
  • 缺點:是增加了空間開銷。
  • 當定義了一個函數後,編譯器就會在記憶體中為其建立一個指令集,當調用這個函數的時候,程式就會跳轉到該指令集處,當函數執行完畢後,程式又會回到原來執行調用該函數語句的下一行繼續執行。
  • 如果對該函數執行上百次調用,那麼就要來回跳轉上百次,這回嚴重影響到程式的執行效率。

    普通函數:函數調用需要時間和空間開銷,調用函數實際上将程式執行流程轉移到被調函數中,被調函數的代碼執行完後,再傳回到調用的地方。

    這種調用操作要求調用前保護好現場并記憶執行的位址,傳回後恢複現場,并按原來儲存的位址繼續執行。對于較長的函數這種開銷可以忽略不計,但對于一些函數體代碼很短,又被頻繁調用的函數,就不能忽視這種開銷。引入内聯函數正是為了解決這個問題,提高程式的運作效率。

    内聯函數:在程式編譯時,編譯器将程式中出現的内聯函數的調用表達式用内聯函數的函數體來進行替換。由于在編譯時将内聯函數體中的代碼替代到程式中,是以會增加目标程式代碼量,進而增加空間開銷,而在時間開銷上不象函數調用時那麼大,可見它是以目标代碼的增加為代價來換取時間的節省。

    注:在不知道具體怎麼操作時,最好先不要使用内聯函數。等完成程式的大部分功能時,再對複合要求的函數進行内聯操作。

參考文獻:

[1]《C++全方位學習》範磊——第十章

[2]《C++程式設計教程(第二版)》錢能——第五章、第六章、第七章

[3]《C++ Primer(第5版)》王剛 楊巨峰——第一章、第六章

[4] 百度搜尋關鍵字:C++函數、内聯函數