C++inline函數(shù)的特性你了解嗎
一.inline的作用(內(nèi)聯(lián)函數(shù))
我們使用關(guān)鍵字inline和函數(shù)定義一起就可以創(chuàng)建一個內(nèi)聯(lián)函數(shù),它的作用就是減少函數(shù)調(diào)用的開銷,假如我們的程序中有一個函數(shù)會頻繁的被調(diào)用,這樣使程序的運(yùn)行速度十分緩慢,那么我們使用內(nèi)聯(lián)函數(shù),就可以解決這種問題,提高程序的運(yùn)行效率.
內(nèi)聯(lián)函數(shù)的定義:
inline void add(int a, int b){ return a+b; }
上面這個就是一個內(nèi)聯(lián)函數(shù),假如我們的程序中頻繁使用add操作時,將其聲明為內(nèi)聯(lián)函數(shù)就可以減少調(diào)用開銷提高效率.
注意:
1.inline關(guān)鍵字是一種"用于實現(xiàn)的關(guān)鍵字",而不是"用于聲明的關(guān)鍵字", 換句話說inline只有放在函數(shù)的定義前,才有可能使該函數(shù)成為內(nèi)聯(lián)函數(shù),放在函數(shù)聲明前無效.
2.另外一點是:在c++的類中定義的成員函數(shù)默認(rèn)就是內(nèi)聯(lián)函數(shù),但前提是在類中定義,因為我們正常的定義類的方式是在頭文件中聲明類的成員變量和成員函數(shù),在原文件中對類的成員函數(shù)進(jìn)行定義,此時成員函數(shù)的定義發(fā)生在類外,所以自然就不再是內(nèi)聯(lián)函數(shù)了,如果還要讓其成為內(nèi)聯(lián)函數(shù),就需要我們手動添加inline.
3.至于第一點中我為什么要說可能使該函數(shù)成為內(nèi)聯(lián)函數(shù),是因為inline是一種推薦型關(guān)鍵字,他并不保證該函數(shù)一定會成為內(nèi)聯(lián)函數(shù),而是編譯器在編譯的時候獲取有inline建議的函數(shù)對其規(guī)模,內(nèi)容,方法等要素進(jìn)行判斷,如果滿足編譯器要求該函數(shù)會成為內(nèi)聯(lián)函數(shù),反之不會成為內(nèi)聯(lián)函數(shù),因此成不成內(nèi)聯(lián)函數(shù)完全由編譯器說了算.
二.inline的實現(xiàn)(注意debug模式下內(nèi)聯(lián)函數(shù)不會展開)
既然內(nèi)聯(lián)函數(shù)可以減小函數(shù)的調(diào)用開銷,那么他是怎么實現(xiàn)的呢?非常簡單,我們在所有調(diào)用內(nèi)聯(lián)函數(shù)的地方將其代碼展開,這樣雖然會使代碼的的量增加,但是減少了調(diào)用的開銷,是一種典型的空間換時間的做法.
我們將編譯器調(diào)到Release模式下使用內(nèi)聯(lián)函數(shù),在匯編指令下就能看見其實現(xiàn)的方式.
源碼:
#include<iostream> using namespace std; inline int add(int a, int b) { return 0; } int main() { int b=add(1, 2); cout << b << endl; return 0; }
(debug模式)反匯編:
在debug模式下我們可以清楚的看到,在程序運(yùn)行到add函數(shù)時,進(jìn)行了2和1兩個參數(shù)的壓棧,以及add函數(shù)的調(diào)用.
(Release模式)反匯編:
此時我們可以看到,像之前的那種參數(shù)壓棧,函數(shù)調(diào)用沒有了,那就是內(nèi)聯(lián)函數(shù),實現(xiàn)成功了,在這里不會再繼續(xù)調(diào)用add函數(shù)了,而是將add函數(shù)直接展開,將其代碼放在這里直接進(jìn)行a+b的運(yùn)算,避免函數(shù)的調(diào)用,增加其運(yùn)行效率.
三.使用inline的注意事項
在上面我說到了,使用內(nèi)聯(lián)函數(shù)是一種消耗空間獲得時間的方法,因此我們得把握好其中的度,當(dāng)程序的規(guī)模過大時,其代碼的運(yùn)行的開銷已經(jīng)遠(yuǎn)遠(yuǎn)超過我們函數(shù)調(diào)用的開銷時,此時收益非常小,再使用內(nèi)聯(lián)函數(shù)就沒有必要了,并且函數(shù)內(nèi)存在遞歸或者循環(huán)時也不能使用內(nèi)聯(lián)函數(shù),編譯器也不會將其變?yōu)閮?nèi)聯(lián)函數(shù).
源碼:
#include<iostream> using namespace std; inline int mul(int a) {//求a的階乘 if (a <= 0) { return 1; } return a * mul(a - 1); } int main() { int b=mul(10); cout << b << endl; return 0; }
(Release模式)反匯編:
此時在Release模式的反匯編指令中我們看到mul函數(shù)并沒有被展開,而是進(jìn)行了函數(shù)調(diào)用,說明編譯器并沒有將其變?yōu)閮?nèi)聯(lián)函數(shù).
四.inline和預(yù)處理的區(qū)別
我們知道預(yù)處理階段會發(fā)生宏替換這一行為,宏替換也就是將代碼中用到宏的地方用宏定義的代碼或數(shù)據(jù)與宏進(jìn)行替換,inline也是將函數(shù)中的代碼復(fù)制到調(diào)用內(nèi)聯(lián)函數(shù)的地方,那么他們有什么區(qū)別呢?宏替換只是單純的替換并不安全,而內(nèi)聯(lián)函數(shù)在使用的時候,編譯器會對內(nèi)聯(lián)函數(shù)調(diào)用的正確性進(jìn)行判斷如果不正確則該操作就不會發(fā)生,因此其更加安全,所以在c++中所有的宏代碼,都應(yīng)該使用內(nèi)聯(lián)函數(shù)進(jìn)行取代.
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
C++詳細(xì)講解互斥量與lock_guard類模板及死鎖
線程的主要優(yōu)勢在于,能夠通過全局變量來共享信息。不過,這種便捷的共享是有代價的:必須確保多個線程不會同時修改同一變量,或者某一線程不會讀取正由其他線程修改的變量。為了防止出現(xiàn)線程某甲試圖訪 問一共享變量時,線程某乙正在對其進(jìn)行修改。引入了互斥量2022-07-07C++實現(xiàn)LeetCode(129.求根到葉節(jié)點數(shù)字之和)
這篇文章主要介紹了C++實現(xiàn)LeetCode(129.求根到葉節(jié)點數(shù)字之和),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C語言使用結(jié)構(gòu)體實現(xiàn)簡單通訊錄
這篇文章主要為大家詳細(xì)介紹了C語言使用結(jié)構(gòu)體實現(xiàn)簡單通訊錄,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-02-02C語言數(shù)據(jù)結(jié)構(gòu)順序表中的增刪改(頭插頭刪)教程示例詳解
這篇文章主要為大家介紹了C語言數(shù)據(jù)結(jié)構(gòu)順序表中增刪改關(guān)于頭插頭刪的教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-02-02Objective-C的內(nèi)省(Introspection)用法小結(jié)
這篇文章主要介紹了Objective-C的內(nèi)省(Introspection)用法,這是面向?qū)ο笳Z言和環(huán)境的一個強(qiáng)大特性,需要的朋友可以參考下2014-07-07