www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > > 充電吧
[導(dǎo)讀]1.inline函數(shù)簡(jiǎn)介inline函數(shù)是由inline關(guān)鍵字來(lái)定義,引入inline函數(shù)的主要原因是用它替代C中復(fù)雜易錯(cuò)不易維護(hù)的宏函數(shù)。2.編譯器對(duì)inline函數(shù)的處理辦法inline對(duì)于編譯器

1.inline函數(shù)簡(jiǎn)介

inline函數(shù)是由inline關(guān)鍵字來(lái)定義,引入inline函數(shù)的主要原因是用它替代C中復(fù)雜易錯(cuò)不易維護(hù)的宏函數(shù)。

2.編譯器對(duì)inline函數(shù)的處理辦法

inline對(duì)于編譯器而言,在編譯階段完成對(duì)inline函數(shù)的處理。將調(diào)用動(dòng)作替換為函數(shù)的本體。但是它只是一種建議,編譯器可以去做,也可以不去做。從邏輯上來(lái)說(shuō),編譯器對(duì)inline函數(shù)的處理步驟一般如下:?
(1)將inline函數(shù)體復(fù)制到inline函數(shù)調(diào)用點(diǎn)處;?
(2)為所用inline函數(shù)中的局部變量分配內(nèi)存空間;?
(3)將inline函數(shù)的的輸入?yún)?shù)和返回值映射到調(diào)用方法的局部變量空間中;?
(4)如果inline函數(shù)有多個(gè)返回點(diǎn),將其轉(zhuǎn)變?yōu)閕nline函數(shù)代碼塊末尾的分支(使用GOTO)。

比如如下代碼:

//求0-9的平方
inline?int?inlineFunc(int?num)
{??
??if(num>9||num<0)
??????return?-1;??
??return?num*num;??
}??

int?main(int?argc,char*?argv[])
{
????int?a=8;
????int?res=inlineFunc(a);
????cout<<"res:"<<res<<endl;
}

inline之后的main函數(shù)代碼類(lèi)似于如下形式:

int?main(int?argc,char*?argv[])
{
????int?a=8;
????{??
????????int?_temp_b=8;??
????????int?_temp;??
????????if?(_temp_q?>9||_temp_q<0)?_temp?=?-1;??
????????else?_temp?=_temp*_temp;??
????????b?=?_temp;??
????}
}

經(jīng)過(guò)以上處理,可消除所有與調(diào)用相關(guān)的痕跡以及性能的損失。inline通過(guò)消除調(diào)用開(kāi)銷(xiāo)來(lái)提升性能。

3.inline函數(shù)使用的一般方法

函數(shù)定義時(shí),在返回類(lèi)型前加上關(guān)鍵字inline即把函數(shù)指定為內(nèi)聯(lián),函數(shù)申明時(shí)可加也可不加。但是建議函數(shù)申明的時(shí)候,也加上inline,這樣能夠達(dá)到”代碼即注釋”的作用。

使用格式如下:

inline?int?functionName(int?first,?int?secend,...)?{/****/};

inline如果只修飾函數(shù)的申明的部分,如下風(fēng)格的函數(shù)foo不能成為內(nèi)聯(lián)函數(shù):

inline?void?foo(int?x,?int?y);?//inline僅與函數(shù)聲明放在一起

void?foo(int?x,?int?y){}

而如下風(fēng)格的函數(shù)foo 則成為內(nèi)聯(lián)函數(shù):

void?foo(int?x,?int?y);

inline?void?foo(int?x,?int?y){}?//inline與函數(shù)定義體放在一起

4.inline函數(shù)的優(yōu)點(diǎn)與缺點(diǎn)

從上面可以知道,inline函數(shù)相對(duì)宏函數(shù)有如下優(yōu)點(diǎn):?
(1)內(nèi)聯(lián)函數(shù)同宏函數(shù)一樣將在被調(diào)用處進(jìn)行代碼展開(kāi),省去了參數(shù)壓棧、棧幀開(kāi)辟與回收,結(jié)果返回等,從而提高程序運(yùn)行速度。

(2)內(nèi)聯(lián)函數(shù)相比宏函數(shù)來(lái)說(shuō),在代碼展開(kāi)時(shí),會(huì)做安全檢查或自動(dòng)類(lèi)型轉(zhuǎn)換(同普通函數(shù)),而宏定義則不會(huì)。?

例如宏函數(shù)和內(nèi)聯(lián)函數(shù):

//宏函數(shù)
#define?MAX(a,b)?((a)>(b)?(a):(b))

//內(nèi)聯(lián)函數(shù)
inline?int?MAX(int?a,int?b)
{
????return?a>b?a:b;
}

使用宏函數(shù)時(shí),其書(shū)寫(xiě)語(yǔ)法也較為苛刻,如果對(duì)宏函數(shù)出現(xiàn)如下錯(cuò)誤的調(diào)用,MAX(a,"Hello");?宏函數(shù)會(huì)錯(cuò)誤地比較int和字符串,沒(méi)有參數(shù)類(lèi)型檢查。但是使用內(nèi)聯(lián)函數(shù)的時(shí)候,會(huì)出現(xiàn)類(lèi)型不匹配的編譯錯(cuò)誤。

(3)在類(lèi)中聲明同時(shí)定義的成員函數(shù),自動(dòng)轉(zhuǎn)化為內(nèi)聯(lián)函數(shù),因此內(nèi)聯(lián)函數(shù)可以訪問(wèn)類(lèi)的成員變量,宏定義則不能。

(4)內(nèi)聯(lián)函數(shù)在運(yùn)行時(shí)可調(diào)試,而宏定義不可以。

萬(wàn)事萬(wàn)物都有陰陽(yáng)兩面,內(nèi)聯(lián)函數(shù)也不外乎如此,使用inline函數(shù),也要三思慎重。inline函數(shù)的缺點(diǎn)總結(jié)如下:?
(1)代碼膨脹。?
inline函數(shù)帶來(lái)的運(yùn)行效率是典型的以空間換時(shí)間的做法。內(nèi)聯(lián)是以代碼膨脹(復(fù)制)為代價(jià),消除函數(shù)調(diào)用帶來(lái)的開(kāi)銷(xiāo)。如果執(zhí)行函數(shù)體內(nèi)代碼的時(shí)間,相比于函數(shù)調(diào)用的開(kāi)銷(xiāo)較大,那么效率的收獲會(huì)很少。另一方面,每一處內(nèi)聯(lián)函數(shù)的調(diào)用都要復(fù)制代碼,將使程序的總代碼量增大,消耗更多的內(nèi)存空間。

(2)inline函數(shù)無(wú)法隨著函數(shù)庫(kù)升級(jí)而升級(jí)。?
如果f是函數(shù)庫(kù)中的一個(gè)inline函數(shù),使用它的用戶會(huì)將f函數(shù)實(shí)體編譯到他們的程序中。一旦函數(shù)庫(kù)實(shí)現(xiàn)者改變f,所有用到f的程序都必須重新編譯。如果f是non-inline的,用戶程序只需重新連接即可。如果函數(shù)庫(kù)采用的是動(dòng)態(tài)連接,那這一升級(jí)的f函數(shù)可以不知不覺(jué)的被程序使用。

(3)是否內(nèi)聯(lián),程序員不可控。?
inline函數(shù)只是對(duì)編譯器的建議,是否對(duì)函數(shù)內(nèi)聯(lián),決定權(quán)在于編譯器。編譯器認(rèn)為調(diào)用某函數(shù)的開(kāi)銷(xiāo)相對(duì)該函數(shù)本身的開(kāi)銷(xiāo)而言微不足道或者不足以為之承擔(dān)代碼膨脹的后果則沒(méi)必要內(nèi)聯(lián)該函數(shù),若函數(shù)出現(xiàn)遞歸,有些編譯器則不支持將其內(nèi)聯(lián)。

5.inline函數(shù)的注意事項(xiàng)

了解了內(nèi)聯(lián)函數(shù)的優(yōu)缺點(diǎn),在使用內(nèi)聯(lián)函數(shù)時(shí),我們也要注意以下幾個(gè)事項(xiàng)和建議。

(1)使用函數(shù)指針調(diào)用內(nèi)聯(lián)函數(shù)將會(huì)導(dǎo)致內(nèi)聯(lián)失敗。?
也就是說(shuō),如果使用函數(shù)指針來(lái)調(diào)用內(nèi)聯(lián)函數(shù),那么就需要獲取inline函數(shù)的地址。如果要取得一個(gè)inline函數(shù)的地址,編譯器就必須為此函數(shù)產(chǎn)生一個(gè)函數(shù)實(shí)體,那么就內(nèi)聯(lián)失敗。

(2)如果函數(shù)體代碼過(guò)長(zhǎng)或者有多重循環(huán)語(yǔ)句,if或witch分支語(yǔ)句或遞歸時(shí),不宜用內(nèi)聯(lián)。

(3)類(lèi)的constructors、destructors和虛函數(shù)往往不是inline函數(shù)的最佳選擇。?
類(lèi)的構(gòu)造函數(shù)(constructors)可能需要調(diào)用父類(lèi)的構(gòu)造函數(shù),析構(gòu)函數(shù)同樣可能需要調(diào)用父類(lèi)的析構(gòu)函數(shù),二者背后隱藏著大量的代碼,不適合作為inline函數(shù)。虛函數(shù)(destructors)往往是運(yùn)行時(shí)確定的,而inline是在編譯時(shí)進(jìn)行的,所以內(nèi)聯(lián)虛函數(shù)往往無(wú)效。如果直接用類(lèi)的對(duì)象來(lái)使用虛函數(shù),那么對(duì)有的編譯器而言,也可起到優(yōu)化作用。

(4)至于內(nèi)聯(lián)函數(shù)是定義在頭文件還是源文件的建議。?

內(nèi)聯(lián)展開(kāi)是在編譯時(shí)進(jìn)行的,只有鏈接的時(shí)候源文件之間才有關(guān)系。所以內(nèi)聯(lián)要想跨源文件必須把實(shí)現(xiàn)寫(xiě)在頭文件里。如果一個(gè)inline函數(shù)會(huì)在多個(gè)源文件中被用到,那么必須把它定義在頭文件中。參考如下示例:

//?base.h
class?Base{protected:void?fun();};

//?base.cpp
#include?base.h
inline?void?Base::fun(){}

//derived.h
#include?base.h
class?Derived:?public?Base{public:void?g();};

//?derived.cpp
void?Derived::g(){fun();}?//VC2010:?error?LNK2019:?unresolved?external?symbol

上面這種錯(cuò)誤,就是因?yàn)閮?nèi)聯(lián)函數(shù)fun()定義在編譯單元base.cpp中,那么其他編譯單元中調(diào)用fun()的地方將無(wú)法解析該符號(hào),因?yàn)樵诰幾g單元base.cpp生成目標(biāo)文件base.obj后,內(nèi)聯(lián)函數(shù)fun()已經(jīng)被替換掉,編譯器不會(huì)為fun()生成函數(shù)實(shí)體,鏈接器自然無(wú)法解析。所以如果一個(gè)inline函數(shù)會(huì)在多個(gè)源文件中被用到,那么必須把它定義在頭文件中。

這里有個(gè)問(wèn)題,當(dāng)在頭文件中定義內(nèi)聯(lián)函數(shù),那么被多個(gè)源文件包含時(shí),如果編譯器因?yàn)閕nline函數(shù)不適合被內(nèi)聯(lián)時(shí),拒絕將inline函數(shù)進(jìn)行內(nèi)聯(lián)處理,那么多個(gè)源文件在編譯生成目標(biāo)文件后都將各自保留一份inline函數(shù)的實(shí)體,這個(gè)時(shí)候程序在連接階段就會(huì)出現(xiàn)重定義錯(cuò)誤。解決辦法是在需要inline的函數(shù)使用static。

//test.h
static?inline?int?max(int?a,int?b)
{
????return?a>b?a:b;
}

事實(shí)上,inline函數(shù)具有內(nèi)部鏈接特性,所以如果實(shí)際上沒(méi)有被內(nèi)聯(lián)處理,也不會(huì)報(bào)重定義錯(cuò)誤,因此使用static修飾inline函數(shù)有點(diǎn)多余。

(5)能否強(qiáng)制編譯器進(jìn)行內(nèi)聯(lián)操作??
也有人可能會(huì)覺(jué)得能否強(qiáng)制編譯器進(jìn)行函數(shù)內(nèi)聯(lián),而不是建議編譯器進(jìn)行內(nèi)聯(lián)呢?很不幸的是目前還不能強(qiáng)制編譯器進(jìn)行函數(shù)內(nèi)聯(lián),如果使用的是MSVC++, 注意__forceinline如同inine一樣,也是一個(gè)用詞不當(dāng)?shù)谋憩F(xiàn),它只是對(duì)編譯器的建議比inline更加強(qiáng)烈,并不能強(qiáng)制編譯器進(jìn)行inline操作。

(6)如何查看函數(shù)是否被內(nèi)聯(lián)處理了??
實(shí)際在VS2012中預(yù)處理了一下,查看預(yù)處理后的.i文件,inline函數(shù)的內(nèi)聯(lián)處理不是在預(yù)處理階段,而是在編譯階段。編譯源文件為匯編代碼或者反匯編查看有沒(méi)有相關(guān)的函數(shù)調(diào)用call,如果沒(méi)有就是被inline了。具體可以參考here。

(7)C++類(lèi)成員函數(shù)定義在類(lèi)體內(nèi)為什么不會(huì)報(bào)重定義錯(cuò)誤??
類(lèi)成員函數(shù)定義在類(lèi)體內(nèi),并隨著類(lèi)的定義放在頭文件中,當(dāng)被不同的源文件包含,那么每個(gè)源文件都應(yīng)該包含了類(lèi)成員函數(shù)的實(shí)體,為何在鏈接的過(guò)程中不會(huì)報(bào)函數(shù)的重定義錯(cuò)誤呢?

原因是:在類(lèi)里定義時(shí),這種函數(shù)會(huì)被編譯器編譯成內(nèi)聯(lián)函數(shù),在類(lèi)外定義的函數(shù)則不會(huì)。內(nèi)聯(lián)函數(shù)的好處是加快程序的運(yùn)行速度,缺點(diǎn)是會(huì)增加程序的尺寸。比較推薦的寫(xiě)法是把一個(gè)經(jīng)常要用的而且實(shí)現(xiàn)起來(lái)比較簡(jiǎn)單的小型函數(shù)放到類(lèi)里去定義,大型函數(shù)最好還是放到類(lèi)外定義。

可能存在的疑問(wèn):類(lèi)體內(nèi)的成員函數(shù)被編譯器內(nèi)聯(lián)處理,但并不是所有的成員函數(shù)都會(huì)被內(nèi)聯(lián)處理,比如包含遞歸的成員函數(shù)。但是實(shí)際測(cè)試,將包含遞歸的成員函數(shù)定義在類(lèi)體內(nèi),被不同的源文件包含并不會(huì)報(bào)重定義錯(cuò)誤,為什么會(huì)這樣呢?請(qǐng)保持著疑問(wèn)與好奇心,請(qǐng)繼續(xù)往下看。

如果編譯器發(fā)現(xiàn)被定義在類(lèi)體內(nèi)的成員函數(shù)無(wú)法被內(nèi)聯(lián)處理,也不會(huì)出現(xiàn)重定義的錯(cuò)誤,因?yàn)镃++中存在5種作用域的級(jí)別,分別是文件域(全局作用域)、命名空間域、類(lèi)域、函數(shù)作用域和代碼塊作用域(局部域)。當(dāng)類(lèi)成員函數(shù)被定義在類(lèi)體內(nèi),那么其作用域也就被限制在類(lèi)域,當(dāng)然定義在類(lèi)體外的函數(shù)作用域也是屬于類(lèi)域的。顯然并不是因?yàn)樽饔糜虻脑蚨粫?huì)產(chǎn)生重定義的錯(cuò)誤。

那么原因究竟是什么呢?其實(shí)很簡(jiǎn)單,類(lèi)體內(nèi)定義的成員函數(shù)就是inline函數(shù),即使不被內(nèi)聯(lián)處理,inline函數(shù)的特性就是不具有外部連接性。所以并不會(huì)與其他源文件中的同名類(lèi)域中的成員函數(shù)發(fā)生沖突,也就不會(huì)造成重定義的錯(cuò)誤。

6.小結(jié)

可以將內(nèi)聯(lián)理解為C++中對(duì)于函數(shù)專(zhuān)有的宏,對(duì)于C的函數(shù)宏的一種改進(jìn)。對(duì)于常量宏,C++提供const替代;而對(duì)于函數(shù)宏,C++提供的方案則是inline。C++ 通過(guò)內(nèi)聯(lián)機(jī)制,既具備宏代碼的效率,又增加了安全性,還可以自由操作類(lèi)的數(shù)據(jù)成員,算是一個(gè)比較完美的解決方案。

上面的結(jié)論和觀點(diǎn),缺乏實(shí)踐和權(quán)威資料支撐,難免存在錯(cuò)誤,僅供參考學(xué)習(xí),如果大家發(fā)現(xiàn)錯(cuò)誤和需要改進(jìn)的地方,請(qǐng)大家留言給予寶貴的建議。


參考文獻(xiàn)

[1]inline函數(shù)?
[2]小問(wèn)題大思考之C++里的inline函數(shù)?
[3]把inline函數(shù)的定義放在頭文件中?
[4]Inline Functions (C++)?
[5]Can I selectively (force) inline a function??
[6]C語(yǔ)言inline詳細(xì)講解?
[7]C++中的作用域與生命周期?

[8]內(nèi)聯(lián)函數(shù)到底有沒(méi)有被嵌入到調(diào)用處呢?



本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專(zhuān)欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢(shì)抑制與過(guò)流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問(wèn)題卻十分常見(jiàn),不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問(wèn)題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(chē)(EV)作為新能源汽車(chē)的重要代表,正逐漸成為全球汽車(chē)產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車(chē)的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車(chē)的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車(chē) 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車(chē)場(chǎng)照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢(shì)逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問(wèn)題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周?chē)娮釉O(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來(lái)解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開(kāi)關(guān)電源具有效率高的特性,而且開(kāi)關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開(kāi)關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉