速度是有代價(jià)的,inline和宏都是用空間換時(shí)間。
成都創(chuàng)新互聯(lián)公司是網(wǎng)站建設(shè)專家,致力于互聯(lián)網(wǎng)品牌建設(shè)與網(wǎng)絡(luò)營(yíng)銷,專業(yè)領(lǐng)域包括成都網(wǎng)站建設(shè)、網(wǎng)站制作、電商網(wǎng)站制作開發(fā)、微信小程序、微信營(yíng)銷、系統(tǒng)平臺(tái)開發(fā),與其他網(wǎng)站設(shè)計(jì)及系統(tǒng)開發(fā)公司不同,我們的整合解決方案結(jié)合了恒基網(wǎng)絡(luò)品牌建設(shè)經(jīng)驗(yàn)和互聯(lián)網(wǎng)整合營(yíng)銷的理念,并將策略和執(zhí)行緊密結(jié)合,且不斷評(píng)估并優(yōu)化我們的方案,為客戶提供全方位的互聯(lián)網(wǎng)品牌整合方案!
使用內(nèi)聯(lián)函數(shù)的時(shí)候要注意:
1.遞歸函數(shù)不能定義為內(nèi)聯(lián)函數(shù)
2.內(nèi)聯(lián)函數(shù)一般適合于不存在while和switch等復(fù)雜的結(jié)構(gòu)且只有1~5條語(yǔ)句的小函數(shù)上,否則編譯系統(tǒng)將該函數(shù)視為普通函數(shù)。
3.內(nèi)聯(lián)函數(shù)只能先定義后使用,否則編譯系統(tǒng)也會(huì)把它認(rèn)為是普通函數(shù)。
4.對(duì)內(nèi)聯(lián)函數(shù)不能進(jìn)行異常的接口聲明。
這個(gè)是內(nèi)聯(lián)函數(shù)。
C語(yǔ)言本身是不支持內(nèi)聯(lián)函數(shù)的,在最新的C標(biāo)準(zhǔn)C99中C語(yǔ)言支持了內(nèi)聯(lián)函數(shù)。
C++支持內(nèi)聯(lián)函數(shù)。
從編譯器的角度:
有些C語(yǔ)言編譯器,例如GNU C提供了內(nèi)聯(lián)函數(shù)的支持。
所有C++編譯器都支持內(nèi)聯(lián)函數(shù)。
如果你的C語(yǔ)言編譯器不支持內(nèi)聯(lián)函數(shù),看看它有多古老,太古老不行(例如 Turbo C 2.0)。如果是C/C++合體編譯器,那就切換到編譯C++模式(例如VisualC++)。
應(yīng)該是c++中才有的,
inline 關(guān)鍵字用來定義一個(gè)類的內(nèi)聯(lián)函數(shù),引入它的主要原因是用它替代C中表達(dá)式形式的宏定義。
表達(dá)式形式的宏定義一例:
#define ExpressionName(Var1,Var2) (Var1+Var2)*(Var1-Var2)
為什么要取代這種形式呢,且聽我道來:
1.
首先談一下在C中使用這種形式宏定義的原因,C語(yǔ)言是一個(gè)效率很高的語(yǔ)言,這種宏定義在形式及使用上像一個(gè)函數(shù),但它使用預(yù)處理器實(shí)現(xiàn),沒有了參數(shù)壓棧,代碼生成等一系列的操作,因此,效率很高,這是它在C中被使用的一個(gè)主要原因。
2.
這種宏定義在形式上類似于一個(gè)函數(shù),但在使用它時(shí),僅僅只是做預(yù)處理器符號(hào)表中的簡(jiǎn)單替換,因此它不能進(jìn)行參數(shù)有效性的檢測(cè),也就不能享受C++編譯器嚴(yán)格類型檢查的好處,另外它的返回值也不能被強(qiáng)制轉(zhuǎn)換為可轉(zhuǎn)換的合適的類型,這樣,它的使用就存在著一系列的隱患和局限性。
3.
在C++中引入了類及類的訪問控制,這樣,如果一個(gè)操作或者說一個(gè)表達(dá)式涉及到類的保護(hù)成員或私有成員,你就不可能使用這種宏定義來實(shí)現(xiàn)(因?yàn)闊o法將this指針放在合適的位置)。
4. inline 推出的目的,也正是為了取代這種表達(dá)式形式的宏定義,它消除了它的缺點(diǎn),同時(shí)又很好地繼承了它的優(yōu)點(diǎn)。
為什么inline能很好地取代表達(dá)式形式的預(yù)定義呢?
對(duì)應(yīng)于上面的1-3點(diǎn),闡述如下:
1. inline 定義的類的內(nèi)聯(lián)函數(shù),函數(shù)的代碼被放入符號(hào)表中,在使用時(shí)直接進(jìn)行替換,(像宏一樣展開),沒有了調(diào)用的開銷,效率也很高。
2.
很明顯,類的內(nèi)聯(lián)函數(shù)也是一個(gè)真正的函數(shù),編譯器在調(diào)用一個(gè)內(nèi)聯(lián)函數(shù)時(shí),會(huì)首先檢查它的參數(shù)的類型,保證調(diào)用正確。然后進(jìn)行一系列的相關(guān)檢查,就像對(duì)待任何一個(gè)真正的函數(shù)一樣。這樣就消除了它的隱患和局限性。
3. inline 可以作為某個(gè)類的成員函數(shù),當(dāng)然就可以在其中使用所在類的保護(hù)成員及私有成員。
在何時(shí)使用inline函數(shù):
首先,你可以使用inline函數(shù)完全取代表達(dá)式形式的宏定義。
另外要注意,內(nèi)聯(lián)函數(shù)一般只會(huì)用在函數(shù)內(nèi)容非常簡(jiǎn)單的時(shí)候,這是因?yàn)?,?nèi)聯(lián)函數(shù)的代碼會(huì)在任何調(diào)用它的地方展開,如果函數(shù)太復(fù)雜,代碼膨脹帶來的惡果很可能會(huì)大于效率的提高帶來的益處。
首先講一下函數(shù)調(diào)用,C語(yǔ)言函數(shù)調(diào)用的過程是:
①將參數(shù)壓棧,一般是從右往左。
②使用call指令,調(diào)用函數(shù)。call指令會(huì)將當(dāng)前指令所在的內(nèi)存位置壓棧以便函數(shù)結(jié)束后返回。
③進(jìn)入函數(shù)體(跳轉(zhuǎn)到另一塊內(nèi)存中),執(zhí)行,執(zhí)行完后,使用通用寄存器或者棧來存儲(chǔ)返回值,使用ret指令返回。
可以看到,函數(shù)調(diào)用是發(fā)生了跳轉(zhuǎn)的,考慮一下跳轉(zhuǎn)大小和指令預(yù)取這些東西,調(diào)用函數(shù)會(huì)加長(zhǎng)執(zhí)行時(shí)間。如果只是調(diào)用幾次,時(shí)間差異可能感覺不出來,不是特別情況也不需要在乎。但函數(shù)被反復(fù)調(diào)用時(shí),性能就會(huì)差很多。
所以有了內(nèi)聯(lián)函數(shù)這玩意,編譯器會(huì)直接將對(duì)內(nèi)聯(lián)函數(shù)的調(diào)用擴(kuò)展為整個(gè)函數(shù)的代碼(幾種情況除外,這個(gè)看書,我也記不?。?,也就是說,不會(huì)使用call和ret指令。所以,這樣做的缺點(diǎn)就是每個(gè)調(diào)用函數(shù)的位置都被擴(kuò)展成了函數(shù)的代碼,會(huì)加大生成的可執(zhí)行文件的大小。所以才會(huì)提倡,將調(diào)用頻繁而函數(shù)本身卻很小的函數(shù)聲明為內(nèi)聯(lián)函數(shù)。
它們的區(qū)別就在這里,跳轉(zhuǎn)和不跳轉(zhuǎn),犧牲時(shí)間還是犧牲空間。
普通的函數(shù)在調(diào)用的時(shí)候需要消耗??臻g,cpu和內(nèi)存利用率會(huì)增高,c99中引入了inline關(guān)鍵字,可以在編譯的時(shí)候,在函數(shù)調(diào)用處直接把函數(shù)像宏一樣展開,這樣在增加代碼空間的情況下降低了cpu和內(nèi)存的使用。
1、如果Inline函數(shù)定義在cpp/c文件中,則本文件里的函數(shù)調(diào)用會(huì)轉(zhuǎn)換為內(nèi)聯(lián)代碼,但是其他文件的函數(shù)調(diào)用還是和普通函數(shù)一樣(gcc標(biāo)準(zhǔn)和c99標(biāo)準(zhǔn)有差別,有可能鏈接時(shí)會(huì)找不到函數(shù)符號(hào))。
2、如果inline函數(shù)定義在.h文件中,則其他文件的函數(shù)調(diào)用也會(huì)轉(zhuǎn)換為內(nèi)聯(lián)代碼。
3、由于內(nèi)聯(lián)函數(shù)調(diào)用時(shí)候不會(huì)壓棧,所以函數(shù)不能是遞歸函數(shù)。