亚洲免费乱码视频,日韩 欧美 国产 动漫 一区,97在线观看免费视频播国产,中文字幕亚洲图片

      1. <legend id="ppnor"></legend>

      2. 
        
        <sup id="ppnor"><input id="ppnor"></input></sup>
        <s id="ppnor"></s>

        C箴言:理解inline化的介入和排除

        字號(hào):

        inline 函數(shù)——多么棒的主意啊!它們看起來(lái)像函數(shù),它們產(chǎn)生的效果也像函數(shù),它們?cè)诟鞣矫娑急群旰玫锰嗵?,而你卻可以在調(diào)用它們時(shí)不招致函數(shù)調(diào)用的成本。你還有什么更多的要求呢?
            實(shí)際上你得到的可能比你想的更多,因?yàn)楸苊夂瘮?shù)調(diào)用的成本只是故事的一部分。在典型情況下,編譯器的優(yōu)化是為了一段連續(xù)的沒(méi)有函數(shù)調(diào)用的代碼設(shè)計(jì)的,所以當(dāng)你 inline 化一個(gè)函數(shù),你可能就使得編譯器能夠?qū)瘮?shù)體實(shí)行上下文相關(guān)的特殊優(yōu)化。大多數(shù)編譯器都不會(huì)對(duì) "outlined" 函數(shù)調(diào)用實(shí)行這樣的優(yōu)化。
            然而,在編程中,就像在生活中,沒(méi)有免費(fèi)午餐,而 inline 函數(shù)也不例外。一個(gè) inline 函數(shù)背后的思想是用函數(shù)本體代替每一處對(duì)這個(gè)函數(shù)的調(diào)用,而且不必拿著統(tǒng)計(jì)表中的 Ph.D. 就可以看出這樣可能會(huì)增加你的目標(biāo)代碼的大小。在有限內(nèi)存的機(jī)器上,過(guò)分熱衷于 inline 化會(huì)使得程序?qū)τ诳捎每臻g來(lái)說(shuō)過(guò)于龐大。即使使用了虛擬內(nèi)存,inline 引起的代碼膨脹也會(huì)導(dǎo)致附加的分頁(yè)調(diào)度,減少指令緩存命中率,以及隨之而來(lái)的性能損失。
            在另一方面,如果一個(gè) inline 函數(shù)本體很短,為函數(shù)本體生成的代碼可能比為一個(gè)函數(shù)調(diào)用生成的代碼還要小。如果是這種情況,inline 化這個(gè)函數(shù)可以實(shí)際上導(dǎo)致更小的目標(biāo)代碼和更高的指令緩存命中率! 記住,inline 是向編譯器發(fā)出的一個(gè)請(qǐng)求,而不是一個(gè)命令。這個(gè)請(qǐng)求能夠以顯式的或隱式的方式提出。隱式的方法就是在一個(gè)類(lèi)定義的內(nèi)部定義一個(gè)函數(shù):
            class Person {
            public:
            ...
            int age() const { return theAge; } // an implicit inline request: age is
            ... // defined in a class definition
            private:
            int theAge;
            };
            這樣的函數(shù)通常是成員函數(shù),不過(guò)我們知道友元函數(shù)也能被定義在類(lèi)的內(nèi)部,如果它們?cè)谀抢?,它們也被隱式地聲明為 inline。
            顯式的聲明一個(gè) inline 函數(shù)的方法是在它的聲明之前加上 inline 關(guān)鍵字。例如,以下就是標(biāo)準(zhǔn) max 模板(來(lái)自 )經(jīng)常用到的的實(shí)現(xiàn)方法:
            template // an explicit inline
            inline const T& std::max(const T& a, const T& b) // request: std::max is
            { return a < b ? b : a; } // preceded by "inline"
            max 是一個(gè)模板的事實(shí)引出一個(gè)觀(guān)察結(jié)論:inline 函數(shù)和模板一般都是定義在頭文件中的。這就使得一些程序員得出結(jié)論斷定函數(shù)模板必須是 inline。這個(gè)結(jié)論是非法的而且有潛在的危害,所以它值得我們考察一下。 inline 函數(shù)一般必須在頭文件內(nèi),因?yàn)榇蠖鄶?shù)構(gòu)建環(huán)境在編譯期間進(jìn)行 inline 化。為了用被調(diào)用函數(shù)的函數(shù)本體替換一個(gè)函數(shù)調(diào)用,編譯器必須知道函數(shù)看起來(lái)像什么樣子。(有一些構(gòu)建環(huán)境可以在連接期間進(jìn)行 inline 化,還有少數(shù)幾個(gè)——比如,基于 .NET Common Language Infrastructure (CLI) 的控制環(huán)境——居然能在運(yùn)行時(shí) inline 化。然而,這些環(huán)境都是例外,并非規(guī)則。inline 化在大多數(shù) C 程序中是一個(gè)編譯時(shí)行為。)
            模板一般在頭文件內(nèi),因?yàn)榫幾g器需要知道一個(gè)模板看起來(lái)像什么以便用到它時(shí)對(duì)它進(jìn)行實(shí)例化。(同樣,也不是全部如此。一些構(gòu)建環(huán)境可以在連接期間進(jìn)行模板實(shí)例化。然而,編譯期實(shí)例化更為普遍。) 模板實(shí)例化與 inline 化無(wú)關(guān)。如果你寫(xiě)了一個(gè)模板,而且你認(rèn)為所有從這個(gè)模板實(shí)例化出來(lái)的函數(shù)都應(yīng)該是 inline 的,那么就聲明這個(gè)模板為 inline,這就是上面的 std::max 的實(shí)現(xiàn)被做的事情。但是如果你為沒(méi)有理由要 inline 化的函數(shù)寫(xiě)了一個(gè)模板,就要避免聲明這個(gè)模板為 inline(無(wú)論顯式的還是隱式的)。inline 化是有成本的,而且你不希望在毫無(wú)預(yù)見(jiàn)的情況下遭遇它們。我們已經(jīng)說(shuō)到 inline 化是如何引起代碼膨脹的,但是,還有其它的成本,過(guò)一會(huì)兒我們?cè)儆懻摗?BR>    在做這件事之前,我們先來(lái)完成對(duì)這個(gè)結(jié)論的考察:inline 是一個(gè)編譯器可能忽略的請(qǐng)求。大多數(shù)編譯器拒絕它們認(rèn)為太復(fù)雜的 inline 函數(shù)(例如,那些包含循環(huán)或者遞歸的),而且,除了最細(xì)碎的以外的全部虛擬函數(shù)的調(diào)用都不會(huì)被 inline 化。不應(yīng)該對(duì)這后一個(gè)結(jié)論感到驚訝。虛擬意味著“等待,直到運(yùn)行時(shí)才能斷定哪一個(gè)函數(shù)被調(diào)用”,而 inline 意味著“執(zhí)行之前,用被調(diào)用函數(shù)取代調(diào)用的地方”。如果編譯器不知道哪一個(gè)函數(shù)將被調(diào)用,你很難責(zé)備它們拒絕 inline 化這個(gè)函數(shù)本體。
            所有這些加在一起,得出:一個(gè)被指定的 inline 函數(shù)是否能真的被 inline 化,取決于你所使用的構(gòu)建環(huán)境——主要是編譯器。幸運(yùn)的是,大多數(shù)編譯器都有一個(gè)診斷層次,在它們不能 inline 化一個(gè)你提出的函數(shù)時(shí),會(huì)導(dǎo)致一個(gè)警告。