C++編碼規(guī)范——內(nèi)聯(lián)

內(nèi)聯(lián)

背景:
函數(shù)的作用:使用函數(shù)能夠避免將相同代碼重寫(xiě)多次的麻煩舵揭,還能減少可執(zhí)行程序的體積,但也會(huì)帶來(lái)程序運(yùn)行時(shí)間上的開(kāi)銷(xiāo)躁锡。
函數(shù)執(zhí)行過(guò)程:函數(shù)調(diào)用在執(zhí)行時(shí)午绳,首先要在棧中為形參和局部變量分配存儲(chǔ)空間,然后還要將實(shí)參的值復(fù)制給形參映之,接下來(lái)還要將函數(shù)的返回地址(該地址指明了函數(shù)執(zhí)行結(jié)束后拦焚,程序應(yīng)該回到哪里繼續(xù)執(zhí)行)放入棧中蜡坊,最后才跳轉(zhuǎn)到函數(shù)內(nèi)部執(zhí)行。這個(gè)過(guò)程是要耗費(fèi)時(shí)間的赎败。
函數(shù)返回后:函數(shù)執(zhí)行 return 語(yǔ)句返回時(shí)秕衙,需要從棧中回收形參和局部變量占用的存儲(chǔ)空間,然后從棧中取出返回地址僵刮,再跳轉(zhuǎn)到該地址繼續(xù)執(zhí)行据忘,這個(gè)過(guò)程也要耗費(fèi)時(shí)間。

總結(jié):使用函數(shù)調(diào)用語(yǔ)句和直接把函數(shù)中的代碼重新抄寫(xiě)一遍相比搞糕,節(jié)省了人力勇吊,但是帶來(lái)了程序運(yùn)行時(shí)間上的額外開(kāi)銷(xiāo)。

一般情況下窍仰,這個(gè)開(kāi)銷(xiāo)可以忽略不計(jì)汉规。但是,如果一個(gè)函數(shù)內(nèi)部沒(méi)有幾條語(yǔ)句驹吮,執(zhí)行時(shí)間本來(lái)就非常短针史,那么這個(gè)函數(shù)調(diào)用產(chǎn)生的額外開(kāi)銷(xiāo)和函數(shù)本身執(zhí)行的時(shí)間相比,就顯得不能忽略了碟狞。假如這樣的函數(shù)在一個(gè)循環(huán)中被上千萬(wàn)次地執(zhí)行啄枕,函數(shù)調(diào)用導(dǎo)致的時(shí)間開(kāi)銷(xiāo)可能就會(huì)使得程序運(yùn)行明顯變慢。

用 inline 關(guān)鍵字較好地解決了函數(shù)調(diào)用開(kāi)銷(xiāo)的問(wèn)題族沃。
內(nèi)聯(lián)函數(shù)和普通函數(shù)的區(qū)別在于:當(dāng)編譯器處理調(diào)用內(nèi)聯(lián)函數(shù)的語(yǔ)句時(shí)频祝,不會(huì)將該語(yǔ)句編譯成函數(shù)調(diào)用的指令,而是直接將整個(gè)函數(shù)體的代碼插人調(diào)用語(yǔ)句處竭业,就像整個(gè)函數(shù)體在調(diào)用處被重寫(xiě)了一遍一樣智润。

有了內(nèi)聯(lián)函數(shù)及舍,就能像調(diào)用一個(gè)函數(shù)那樣方便地重復(fù)使用一段代碼未辆,而不需要付出執(zhí)行函數(shù)調(diào)用的額外開(kāi)銷(xiāo)。很顯然锯玛,使用內(nèi)聯(lián)函數(shù)會(huì)使最終可執(zhí)行程序的體積增加咐柜。

內(nèi)聯(lián)函數(shù)中的代碼應(yīng)該只是很簡(jiǎn)單、執(zhí)行很快的幾條語(yǔ)句攘残。如果一個(gè)函數(shù)較為復(fù)雜拙友,它執(zhí)行的時(shí)間可能上萬(wàn)倍于函數(shù)調(diào)用的額外開(kāi)銷(xiāo),那么將其作為內(nèi)聯(lián)函數(shù)處理的結(jié)果是付出讓代碼體積增加不少的代價(jià)歼郭,卻只使速度提高了萬(wàn)分之一遗契,這顯然是不劃算的。

有時(shí)函數(shù)看上去很簡(jiǎn)單病曾,例如只有一個(gè)包含一兩條語(yǔ)句的循環(huán)牍蜂,但該循環(huán)的執(zhí)行次數(shù)可能很多漾根,要消耗大量時(shí)間,那么這種情況也不適合將其實(shí)現(xiàn)為內(nèi)聯(lián)函數(shù)鲫竞。

另外辐怕,需要注意的是,inline要放在函數(shù)定義前从绘,而不是函數(shù)聲明前寄疏。

內(nèi)聯(lián)函數(shù)的使用規(guī)則:
只有當(dāng)函數(shù)只有 10 行甚至更少時(shí)才將其定義為內(nèi)聯(lián)函數(shù)
精短的存取函數(shù)聲明稱(chēng)內(nèi)聯(lián)
謹(jǐn)慎對(duì)待析構(gòu)函數(shù), 析構(gòu)函數(shù)往往比其表面看起來(lái)要更長(zhǎng), 因?yàn)橛须[含的成員和基類(lèi)析構(gòu)函數(shù)被調(diào)用
包含循環(huán)或 switch 語(yǔ)句的函數(shù)常常是得不償失 (除非在大多數(shù)情況下, 這些循環(huán)或 switch 語(yǔ)句從不被執(zhí)行)
虛函數(shù)和遞歸函數(shù)不會(huì)被內(nèi)聯(lián)
特定場(chǎng)景規(guī)則:

  • 完全在類(lèi)/結(jié)構(gòu)/聯(lián)合定義中定義的函數(shù),無(wú)論是成員函數(shù)還是友元函數(shù)僵井,如果它添加到全局模塊 (C++20 起)陕截,則為隱式的內(nèi)聯(lián)函數(shù)。
  • 聲明為constexpr的函數(shù)是一個(gè)隱式的內(nèi)聯(lián)函數(shù)(C++11)
  • 聲明為deleted的函數(shù)是一個(gè)隱式的內(nèi)聯(lián)函數(shù)(C++11)(暫未明確:deleted的函數(shù)內(nèi)聯(lián)個(gè)什么勁)
  • 靜態(tài)全局區(qū)的變量驹沿,如:靜態(tài)類(lèi)成員或者命名空間范圍的變量艘策,可以聲明成內(nèi)聯(lián)變量
  • 聲明成constexpr的靜態(tài)類(lèi)成員變量(命名空間范圍變量除外)是一個(gè)隱性的內(nèi)聯(lián)變量

優(yōu)點(diǎn): 當(dāng)函數(shù)體比較小的時(shí)候, 內(nèi)聯(lián)該函數(shù)可以令目標(biāo)代碼更加高效. 對(duì)于存取函數(shù)以及其它函數(shù)體比較短, 性能關(guān)鍵的函數(shù), 鼓勵(lì)使用內(nèi)聯(lián).
缺點(diǎn): 濫用內(nèi)聯(lián)將導(dǎo)致程序變慢. 內(nèi)聯(lián)可能使目標(biāo)代碼量或增或減, 這取決于內(nèi)聯(lián)函數(shù)的大小. 內(nèi)聯(lián)非常短小的存取函數(shù)通常會(huì)減少代碼大小, 但內(nèi)聯(lián)一個(gè)相當(dāng)大的函數(shù)將戲劇性的增加代碼大小. 現(xiàn)代處理器由于更好的利用了指令緩存, 小巧的代碼往往執(zhí)行更快。
注意:遞歸函數(shù)不應(yīng)該聲明成內(nèi)聯(lián)函數(shù).(遞歸調(diào)用堆棧的展開(kāi)并不像循環(huán)那么簡(jiǎn)單, 比如遞歸層數(shù)在編譯時(shí)可能是未知的, 大多數(shù)編譯器都不支持內(nèi)聯(lián)遞歸函數(shù)). 虛函數(shù)內(nèi)聯(lián)的主要原因則是想把它的函數(shù)體放在類(lèi)定義內(nèi)

notes:
查看匯編代碼是否內(nèi)聯(lián)時(shí)渊季,應(yīng)該用release版本朋蔫,debug版本看不到內(nèi)聯(lián)的情況
在線編譯器,可驗(yàn)證不同的編譯器下的編譯選項(xiàng)或差異性
參考資料:
cppreference:inline
被知乎大佬嘲諷后的一個(gè)月却汉,我重新研究了一下內(nèi)聯(lián)函數(shù)
C++ 風(fēng)格指南

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末驯妄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子合砂,更是在濱河造成了極大的恐慌青扔,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翩伪,死亡現(xiàn)場(chǎng)離奇詭異微猖,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)缘屹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)凛剥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人轻姿,你說(shuō)我怎么就攤上這事犁珠。” “怎么了互亮?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵犁享,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我豹休,道長(zhǎng)炊昆,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮凤巨,結(jié)果婚禮上屏积,老公的妹妹穿的比我還像新娘。我一直安慰自己磅甩,他們只是感情好炊林,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著卷要,像睡著了一般渣聚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上僧叉,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天奕枝,我揣著相機(jī)與錄音,去河邊找鬼瓶堕。 笑死隘道,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的郎笆。 我是一名探鬼主播谭梗,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼宛蚓!你這毒婦竟也來(lái)了激捏?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤凄吏,失蹤者是張志新(化名)和其女友劉穎远舅,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體痕钢,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡图柏,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了任连。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚤吹。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖课梳,靈堂內(nèi)的尸體忽然破棺而出距辆,到底是詐尸還是另有隱情余佃,我是刑警寧澤暮刃,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站爆土,受9級(jí)特大地震影響椭懊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一氧猬、第九天 我趴在偏房一處隱蔽的房頂上張望背犯。 院中可真熱鬧,春花似錦盅抚、人聲如沸漠魏。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)柱锹。三九已至,卻和暖如春丰包,著一層夾襖步出監(jiān)牢的瞬間禁熏,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工邑彪, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瞧毙,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓寄症,卻偏偏與公主長(zhǎng)得像宙彪,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子有巧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容