• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            醬壇子

            專注C++技術(shù) 在這里寫下自己的學(xué)習(xí)心得 感悟 和大家討論 共同進(jìn)步(歡迎批評(píng)!!!)

              C++博客 :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
              66 Posts :: 16 Stories :: 236 Comments :: 0 Trackbacks

            公告

            王一偉 湖南商學(xué)院畢業(yè) 電子信息工程專業(yè)

            常用鏈接

            留言簿(19)

            我參與的團(tuán)隊(duì)

            搜索

            •  

            積分與排名

            • 積分 - 387222
            • 排名 - 64

            最新隨筆

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            自己對(duì) inline 函數(shù)做個(gè)總結(jié)

            (一)inline函數(shù)(摘自C++ Primer的第三版)

            ?????????在函數(shù)聲明或定義中函數(shù)返回類型前加上關(guān)鍵字inline即把min()指定為內(nèi)聯(lián)。

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

            ??????inline函數(shù)對(duì)編譯器而言必須是可見的,以便它能夠在調(diào)用點(diǎn)內(nèi)展開該函數(shù)。與非inline函數(shù)不同的是,inline函數(shù)必須在調(diào)用該函數(shù)的每個(gè)文本文件中定義。當(dāng)然,對(duì)于同一程序的不同文件,如果inline函數(shù)出現(xiàn)的話,其定義必須相同。對(duì)于由兩個(gè)文件compute.C和draw.C構(gòu)成的程序來說,程序員不能定義這樣的min()函數(shù),它在compute.C中指一件事情,而在draw.C中指另外一件事情。如果兩個(gè)定義不相同,程序?qū)?huì)有未定義的行為:

            ??????為保證不會(huì)發(fā)生這樣的事情,建議把inline函數(shù)的定義放到頭文件中。在每個(gè)調(diào)用該inline函數(shù)的文件中包含該頭文件。這種方法保證對(duì)每個(gè)inline函數(shù)只有一個(gè)定義,且程序員無需復(fù)制代碼,并且不可能在程序的生命期中引起無意的不匹配的事情。

            (二)內(nèi)聯(lián)函數(shù)的編程風(fēng)格(摘自高質(zhì)量C++/C 編程指南)

            關(guān)鍵字inline 必須與函數(shù)定義體放在一起才能使函數(shù)成為內(nèi)聯(lián),僅將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ù)定義體放在一起{}所以說,inline 是一種“用于實(shí)現(xiàn)的關(guān)鍵字”,而不是一種“用于聲明的關(guān)鍵字”。一般地,用戶可以閱讀函數(shù)的聲明,但是看不到函數(shù)的定義。盡管在大多數(shù)教科書中內(nèi)聯(lián)函數(shù)的聲明、定義體前面都加了inline 關(guān)鍵字,但我認(rèn)為inline 不應(yīng)該出現(xiàn)在函數(shù)的聲明中。這個(gè)細(xì)節(jié)雖然不會(huì)影響函數(shù)的功能,但是體現(xiàn)了高質(zhì)量C++/C 程序設(shè)計(jì)風(fēng)格的一個(gè)基本原則:聲明與定義不可混為一談,用戶沒有必要、也不應(yīng)該知道函數(shù)是否需要內(nèi)聯(lián)。

            定義在類聲明之中的成員函數(shù)將自動(dòng)地成為內(nèi)聯(lián)函數(shù),例如class A{public:void Foo(int x, int y) {? } // 自動(dòng)地成為內(nèi)聯(lián)函數(shù)}將成員函數(shù)的定義體放在類聲明之中雖然能帶來書寫上的方便,但不是一種良好的編程風(fēng)格,上例應(yīng)該改成:// 頭文件class A{public:void Foo(int x, int y);}// 定義文件inline void A::Foo(int x, int y){}?慎用內(nèi)聯(lián)內(nèi)聯(lián)能提高函數(shù)的執(zhí)行效率,為什么不把所有的函數(shù)都定義成內(nèi)聯(lián)函數(shù)?如果所有的函數(shù)都是內(nèi)聯(lián)函數(shù),還用得著“內(nèi)聯(lián)”這個(gè)關(guān)鍵字嗎?內(nèi)聯(lián)是以代碼膨脹(復(fù)制)為代價(jià),僅僅省去了函數(shù)調(diào)用的開銷,從而提高函數(shù)的執(zhí)行效率。如果執(zhí)行函數(shù)體內(nèi)代碼的時(shí)間,相比于函數(shù)調(diào)用的開銷較大,那么效率的收獲會(huì)很少。另一方面,每一處內(nèi)聯(lián)函數(shù)的調(diào)用都要復(fù)制代碼,將使程序的總代碼量增大,消耗更多的內(nèi)存空間。以下情況不宜使用內(nèi)聯(lián):(1)如果函數(shù)體內(nèi)的代碼比較長,使用內(nèi)聯(lián)將導(dǎo)致內(nèi)存消耗代價(jià)較高。(2)如果函數(shù)體內(nèi)出現(xiàn)循環(huán),那么執(zhí)行函數(shù)體內(nèi)代碼的時(shí)間要比函數(shù)調(diào)用的開銷大。類的構(gòu)造函數(shù)和析構(gòu)函數(shù)容易讓人誤解成使用內(nèi)聯(lián)更有效。要當(dāng)心構(gòu)造函數(shù)和析構(gòu)函數(shù)可能會(huì)隱藏一些行為,如“偷偷地”執(zhí)行了基類或成員對(duì)象的構(gòu)造函數(shù)和析構(gòu)函數(shù)。所以不要隨便地將構(gòu)造函數(shù)和析構(gòu)函數(shù)的定義體放在類聲明中。一個(gè)好的編譯器將會(huì)根據(jù)函數(shù)的定義體,自動(dòng)地取消不值得的內(nèi)聯(lián)(這進(jìn)一步說明了inline 不應(yīng)該出現(xiàn)在函數(shù)的聲明中)。


            注意點(diǎn):

            內(nèi)聯(lián)函數(shù)既能夠去除函數(shù)調(diào)用所帶來的效率負(fù)擔(dān)又能夠保留一般函數(shù)的優(yōu)點(diǎn)。然而,內(nèi)聯(lián)函數(shù)并不是萬能藥, ?
            ? 在一些情況下,它甚至能夠降低程序的性能。因此在使用的時(shí)候應(yīng)該慎重。 ?
            ? ? ? ? ? 1.我們先來看看內(nèi)聯(lián)函數(shù)給我們帶來的好處:從一個(gè)用戶的角度來看,內(nèi)聯(lián)函數(shù)看起來和普通函數(shù)一樣, ?
            ? 它可以有參數(shù)和返回值,也可以有自己的作用域,然而它卻不會(huì)引入一般函數(shù)調(diào)用所帶來的負(fù)擔(dān)。另外, ?
            ? 它可以比宏更安全更容易調(diào)試。 ?
            ? ? 當(dāng)然有一點(diǎn)應(yīng)該意識(shí)到,inline ? specifier僅僅是對(duì)編譯器的建議,編譯器有權(quán)利忽略這個(gè)建議。那么編譯器是 ?
            ? ? 如何決定函數(shù)內(nèi)聯(lián)與否呢?一般情況下關(guān)鍵性因素包括函數(shù)體的大小,是否有局部對(duì)象被聲明,函數(shù)的復(fù)雜性等等。 ?
            ? ? ? ? ? 2.那么如果一個(gè)函數(shù)被聲明為inline但是卻沒有被內(nèi)聯(lián)將會(huì)發(fā)生什么呢?理論上,當(dāng)編譯器拒絕內(nèi)聯(lián)一個(gè) ?
            ? 函數(shù)的時(shí)候,那個(gè)函數(shù)會(huì)像普通函數(shù)一樣被對(duì)待,但是還會(huì)出現(xiàn)一些其他的問題。例如下面這段代碼: ?
            ? // ? filename ? Time.h ?
            ? #include<ctime> ?
            ? #include<iostream> ?
            ? using ? namespace ? std; ?
            ? class ? Time ?
            ? { ?
            ? public: ?
            ? ? ? ? ? inline ? void ? Show() ? { ? for ? (int ? i ? = ? 0; ? i<10; ? i++) ? cout<<time(0)<<endl;} ?
            ? }; ?
            ? ? ? ? ? 因?yàn)槌蓡T函數(shù)Time::Show()包括一個(gè)局部變量和一個(gè)for循環(huán),所以編譯器一般拒絕inline,并且把它當(dāng)作一個(gè)普通的成員函數(shù)。但是這個(gè)包含類聲明的頭文件會(huì)被單獨(dú)的#include進(jìn)各個(gè)獨(dú)立的編譯單元中: ?
            ? ? ? ? ? // ? filename ? f1.cpp ?
            ? #include ? "Time.hj" ?
            ? void ? f1() ?
            ? { ?
            ? ? ? ? ? Time ? t1; ?
            ? ? ? ? ? t1.Show(); ?
            ? } ?
            ? ?
            ? // ? filename ? f2.cpp ?
            ? #include ? "Time.h" ?
            ? void ? f2() ?
            ? { ?
            ? ? ? ? ? Time ? t2; ?
            ? ? ? ? ? t2.Show(); ?
            ? } ?
            ? 結(jié)果編譯器為這個(gè)程序生成了兩個(gè)相同成員函數(shù)的拷貝: ?
            ? void ? f1(); ?
            ? void ? f2(); ?
            ? int ? main() ?
            ? { ?
            ? ? ? ? ? f1(); ? ?
            ? ? ? ? ? f2(); ?
            ? ? ? return ? 0; ?
            ? } ?
            ? ?
            ? 當(dāng)程序被鏈接的時(shí)候,linker將會(huì)面對(duì)兩個(gè)相同的Time::Show()拷貝,于是函數(shù)重 ?
            ? 定義的連接錯(cuò)誤發(fā)生。但是老一些的C++實(shí)現(xiàn)對(duì)付這種情況的辦法是通過把一個(gè) ?
            ? un-inlined函數(shù)當(dāng)作static來處理。因此每一份函數(shù)拷貝僅僅在自己的編譯單元中 ?
            ? 可見,這樣鏈接錯(cuò)誤就解決了,但是在程序中卻會(huì)留下多份函數(shù)拷貝。在這種情況 ?
            ? 下,程序的性能不但沒有提升,反而增加了編譯和鏈接時(shí)間以及最終可執(zhí)行體的大小。 ?
            ? 但是幸運(yùn)的是,新的C++標(biāo)準(zhǔn)中關(guān)于un-inlined函數(shù)的說法已經(jīng)改變。一個(gè)符合標(biāo)準(zhǔn) ?
            ? C++實(shí)現(xiàn)應(yīng)該只生成一份函數(shù)拷貝。然而,要想所有的編譯器都支持這一點(diǎn)可能還 ?
            ? 需要很長時(shí)間。 ?
            ? 另外關(guān)于內(nèi)聯(lián)函數(shù)還有兩個(gè)更令人頭疼的問題。第一個(gè)問題是該如何進(jìn)行維護(hù)。 ?
            ? 一個(gè)函數(shù)開始的時(shí)候可能以內(nèi)聯(lián)的形式出現(xiàn),但是隨著系統(tǒng)的擴(kuò)展,函數(shù)體可能要 ?
            ? 求添加額外的功能,結(jié)果內(nèi)聯(lián)函數(shù)就變得不太可能,因此需要把inline ? specifier ?
            ? 去除以及把函數(shù)體放到一個(gè)單獨(dú)的源文件中。另一個(gè)問題是當(dāng)內(nèi)聯(lián)函數(shù)被應(yīng)用在代 ?
            ? 碼庫的時(shí)候產(chǎn)生。當(dāng)內(nèi)聯(lián)函數(shù)改變的時(shí)候,用戶必須重新編譯他們的代碼以反映這 ?
            ? 種改變。然而對(duì)于一個(gè)非內(nèi)聯(lián)函數(shù),用戶僅僅需要重新鏈接就可以了。 ?
            ? 這里想要說的是,內(nèi)聯(lián)函數(shù)并不是一個(gè)增強(qiáng)性能的靈丹妙藥。只有當(dāng)函數(shù)非常短小 ?
            ? 的時(shí)候它才能得到我們想要的效果,但是如果函數(shù)并不是很短而且在很多地方都被 ?
            ? 調(diào)用的話,那么將會(huì)使得可執(zhí)行體的體積增大。最令人煩惱的還是當(dāng)編譯器拒絕內(nèi)聯(lián) ?
            ? 的時(shí)候。在老的實(shí)現(xiàn)中,結(jié)果很不盡人意,雖然在新的實(shí)現(xiàn)中有很大的改善,但是 ?
            ? 仍然還是不那么完善的。一些編譯器能夠足夠的聰明來指出哪些函數(shù)可以內(nèi)聯(lián)哪些 ?
            ? 不能,但是,大多數(shù)編譯器就不那么聰明了,因此這就需要我們的經(jīng)驗(yàn)來判斷。 ?
            ? 如果內(nèi)聯(lián)函數(shù)不能增強(qiáng)行能,就避免使用它! ?
            ? */ ?
            ? ?
            ? /* ?
            ? 用指針代替數(shù)組 ? ?
            ? 在許多種情況下,可以用指針運(yùn)算代替數(shù)組索引,這樣做常常能產(chǎn)生又快又短的 ?
            ? 代碼。與數(shù)組索引相比,指針一般能使代碼速度更快,占用空間更少。使用多維數(shù) ?
            ? 組時(shí)差異更明顯。下面的代碼作用是相同的,但是效率不一樣。 ?
            ? ?
            ? char* ? pBuffer ? = ? new ? char[100]; ?
            ? nTestNumber ? = ? 0; ?
            ? ?
            ? for(dwIndex ? = ? 0;dwIndex ? < ? 100;dwIndex ? ++) ?
            ? { ?
            ? nTestNumber ? = ? pBuffer[dwIndex]; ?
            ? } ?
            ? ?
            ? char* ? pTemp ? = ? pBuffer; ?
            ? for(dwIndex ? = ? 0;dwIndex ? < ? 100;dwIndex ? ++) ?
            ? { ?
            ? nTestNumber ? = ? *(pTemp ? ++); ?
            ? } ?
            ? ?
            ? 指針方法的優(yōu)點(diǎn)是,pBuffer的地址每次裝入地址pTemp后,在每次循環(huán)中只需對(duì)pTemp增量操作。 ?
            ? 在數(shù)組索引方法中,每次循環(huán)中都必須進(jìn)行基于dwIndex值求數(shù)組下標(biāo)的復(fù)雜運(yùn)算。 ?
            ? */??

            posted on 2006-10-16 20:39 @王一偉 閱讀(9793) 評(píng)論(6)  編輯 收藏 引用 所屬分類: 4. C++

            Feedback

            # re: inline函數(shù) 2006-10-29 10:48 Optimistic
            inline函數(shù)的效率我一直是質(zhì)疑的 曾經(jīng)測(cè)過100萬次函數(shù)調(diào)用時(shí)INLINE和非INLINE的時(shí)間開銷 結(jié)果居然INLINE輸了。。。  回復(fù)  更多評(píng)論
              

            # re: inline函數(shù) 2006-12-14 10:55 王一偉
            啊 哦
            我算了1億多次 還是inline強(qiáng)啊
            有時(shí)候不是寫了inline就一定是inline的:)
            你再測(cè)試下 看看是不是哪里出了問題
              回復(fù)  更多評(píng)論
              

            # re: inline函數(shù) 2007-12-29 17:13 Solomon Joh
            可以說明一下什么時(shí)候?qū)懥薸nline就不一定是inline啊?就像聲明寄存器變量不一定在寄存器里?但是寄存器是編譯器負(fù)責(zé),inline誰負(fù)責(zé)啊?  回復(fù)  更多評(píng)論
              

            # re: inline函數(shù) 2007-12-30 08:03 @王一偉
            呵呵 是的 寄存器變量的分配在編譯時(shí)獲得,編譯時(shí)會(huì)確定變量數(shù)據(jù)段的地址,包括寄存器變量。

            inline也是編譯器負(fù)責(zé) 原生C++都是在編譯時(shí)進(jìn)行inline化,而C++/CLI可以支持運(yùn)行時(shí)的inline化

            不知道是不是可以理解C++/CLI為一種動(dòng)態(tài)語言了 呵呵,我對(duì)這不是太清楚 Solomon Jon可以解釋下  回復(fù)  更多評(píng)論
              

            # re: inline函數(shù) 2007-12-30 08:12 @王一偉
            inline化算是編譯時(shí)的一種優(yōu)化,比如里面有for循環(huán)的時(shí)候,還有遞歸調(diào)用什么的,編譯器就會(huì)自動(dòng)優(yōu)化成非inline函數(shù),inline的會(huì)導(dǎo)致代碼體積上升過快 呵呵。

            這個(gè)是編譯到代碼段的行為。  回復(fù)  更多評(píng)論
              

            # re: inline函數(shù)[未登錄] 2012-05-15 16:42 阿南
            說的挺好  回復(fù)  更多評(píng)論
              

            久久亚洲精品人成综合网| 久久国产免费观看精品| 丰满少妇人妻久久久久久| 久久综合九色综合久99| 97久久综合精品久久久综合| 久久亚洲AV成人无码软件| 久久午夜电影网| 久久精品麻豆日日躁夜夜躁| 久久亚洲精品成人无码网站| 国产日韩久久久精品影院首页| 日本人妻丰满熟妇久久久久久| 亚洲国产香蕉人人爽成AV片久久| 日韩一区二区久久久久久| 久久精品aⅴ无码中文字字幕重口| 亚洲国产一成久久精品国产成人综合| 亚洲国产精品人久久| 亚洲国产成人久久精品影视| 久久91亚洲人成电影网站| 国产精品久久久久久吹潮| 99久久人妻无码精品系列蜜桃| 久久久久亚洲av无码专区| 天天躁日日躁狠狠久久| 日韩乱码人妻无码中文字幕久久 | 久久精品二区| 国产成人久久精品麻豆一区| 99热都是精品久久久久久| 久久99国产精品久久99果冻传媒| 国产V亚洲V天堂无码久久久| 久久国产精品国产自线拍免费| 国产99精品久久| 91精品观看91久久久久久| 少妇久久久久久被弄到高潮| 精品伊人久久久| 人妻少妇久久中文字幕| 国产精品欧美久久久天天影视 | 久久国产精品偷99| 久久久久国色AV免费观看| 久久天天婷婷五月俺也去| 伊人久久无码中文字幕| 777久久精品一区二区三区无码| 亚洲乱码日产精品a级毛片久久|