• <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++ Programmer's Cookbook

            {C++ 基礎(chǔ)} {C++ 高級(jí)} {C#界面,C++核心算法} {設(shè)計(jì)模式} {C#基礎(chǔ)}

            c++代碼優(yōu)化總結(jié)

            一. 優(yōu)化之前
            在進(jìn)行優(yōu)化之前,我們首先應(yīng)該做的是發(fā)現(xiàn)我們代碼的瓶頸(bottleneck)在哪里。然而當(dāng)你做這件事情的時(shí)候切忌從一個(gè)debug-version進(jìn)行推斷,因?yàn)閐ebug-version中包含了許多額外的代碼。一個(gè)debug-version可執(zhí)行體要比release-version大出40%。那些額外的代碼都是用來(lái)支持調(diào)試的,比如說(shuō)符號(hào)的查找。大多數(shù)實(shí)現(xiàn)都為debug-version和release-version提供了不同的operator new以及庫(kù)函數(shù)。而且,一個(gè)release-version的執(zhí)行體可能已經(jīng)通過(guò)多種途徑進(jìn)行了優(yōu)化,包括不必要的臨時(shí)對(duì)象的消除,循環(huán)展開,把對(duì)象移入寄存器,內(nèi)聯(lián)等等。
            另外,我們要把調(diào)試和優(yōu)化區(qū)分開來(lái),它們是在完成不同的任務(wù)。 debug-version 是用來(lái)追捕bugs以及檢查程序是否有邏輯上的問(wèn)題。release-version則是用來(lái)做一些性能上的調(diào)整以及進(jìn)行優(yōu)化。
            下面就讓我們來(lái)看看有哪些代碼優(yōu)化技術(shù)吧:

            二. 聲明的放置
            程序中變量和對(duì)象的聲明放在什么位置將會(huì)對(duì)性能產(chǎn)生顯著影響。同樣,對(duì)postfix和prefix運(yùn)算符的選擇也會(huì)影響性能。這一部分我們集中討論四個(gè)問(wèn)題:初始化v.s 賦值,在程序確實(shí)要使用的地方放置聲明,構(gòu)造函數(shù)的初始化列表,prefix v.s postfix運(yùn)算符。
            (1) 請(qǐng)使用初始化而不是賦值
            在C語(yǔ)言中只允許在一個(gè)函數(shù)體的開頭進(jìn)行變量的聲明,然而在C++中聲明可以出現(xiàn)在程序的任何位置。這樣做的目的是希望把對(duì)象的聲明拖延到確實(shí)要使用它的時(shí)候再進(jìn)行。這樣做可以有兩個(gè)好處:1. 確保了對(duì)象在它被使用前不會(huì)被程序的其他部分惡意修改。如果對(duì)象在開頭就被聲明然而卻在20行以后才被使用的話,就不能做這樣的保證。2. 使我們有機(jī)會(huì)通過(guò)用初始化取代賦值來(lái)達(dá)到性能的提升,從前聲明只能放在開頭,然而往往開始的時(shí)候我們還沒有獲得我們想要的值,因此初始化所帶來(lái)的好處就無(wú)法被應(yīng)用。但是現(xiàn)在我們可以在我們獲得了想要的值的時(shí)候直接進(jìn)行初始化,從而省去了一步。注意,或許對(duì)于基本類型來(lái)說(shuō),初始化和賦值之間可能不會(huì)有什么差異,但是對(duì)于用戶定義的類型來(lái)說(shuō),二者就會(huì)帶來(lái)顯著的不同,因?yàn)橘x值會(huì)多進(jìn)行一次函數(shù)調(diào)用----operator =。因此當(dāng)我們?cè)谫x值和初始化之間進(jìn)行選擇的話,初始化應(yīng)該是我們的首選。
            (2) 把聲明放在合適的位置上
            在一些場(chǎng)合,通過(guò)移動(dòng)聲明到合適的位置所帶來(lái)的性能提升應(yīng)該引起我們足夠的重視。例如:
            bool is_C_Needed();
            void use()
            {
            C c1;
            if (is_C_Needed() == false)
            {
            return; //c1 was not needed
            }
            //use c1 here
            return;
            }
            上面這段代碼中對(duì)象c1即使在有可能不使用它的情況下也會(huì)被創(chuàng)建,這樣我們就會(huì)為它付出不必要的花費(fèi),有可能你會(huì)說(shuō)一個(gè)對(duì)象c1能浪費(fèi)多少時(shí)間,但是如果是這種情況呢:C c1[1000];我想就不是說(shuō)浪費(fèi)就浪費(fèi)了。但是我們可以通過(guò)移動(dòng)聲明c1的位置來(lái)改變這種情況:
            void use()
            {
            if (is_C_Needed() == false)
            {
            return; //c1 was not needed
            }
            C c1; //moved from the block's beginning
            //use c1 here
            return;
            }
            怎么樣,程序的性能是不是已經(jīng)得到很大的改善了呢?因此請(qǐng)仔細(xì)分析你的代碼,把聲明放在合適的位置上,它所帶來(lái)的好處是你難以想象的。
            (3) 初始化列表
            我們都知道,初始化列表一般是用來(lái)初始化const或者reference數(shù)據(jù)成員。但是由于他自身的性質(zhì),我們可以通過(guò)使用初始化列表來(lái)實(shí)現(xiàn)性能的提升。我們先來(lái)看一段程序:
            class Person
            {
            private:
            C c_1;
            C c_2;
            public:
            Person(const C& c1, const C& c2 ): c_1(c1), c_2(c2) {}
            };
            當(dāng)然構(gòu)造函數(shù)我們也可以這樣寫:
            Person::Person(const C& c1, const C& c2)
            {
            c_1 = c1;
            c_2 = c2;
            }
            那么究竟二者會(huì)帶來(lái)什么樣的性能差異呢,要想搞清楚這個(gè)問(wèn)題,我們首先要搞清楚二者是如何執(zhí)行的,先來(lái)看初始化列表:數(shù)據(jù)成員的聲明操作都是在構(gòu)造函數(shù)執(zhí)行之前就完成了,在構(gòu)造函數(shù)中往往完成的只是賦值操作,然而初始化列表直接是在數(shù)據(jù)成員聲明的時(shí)候就進(jìn)行了初始化,因此它只執(zhí)行了一次copy constructor。再來(lái)看在構(gòu)造函數(shù)中賦值的情況:首先,在構(gòu)造函數(shù)執(zhí)行前會(huì)通過(guò)default constructor創(chuàng)建數(shù)據(jù)成員,然后在構(gòu)造函數(shù)中通過(guò)operator =進(jìn)行賦值。因此它就比初始化列表多進(jìn)行了一次函數(shù)調(diào)用。性能差異就出來(lái)了。但是請(qǐng)注意,如果你的數(shù)據(jù)成員都是基本類型的話,那么為了程序的可讀性就不要使用初始化列表了,因?yàn)榫幾g器對(duì)兩者產(chǎn)生的匯編代碼是相同的。
            (4) postfix VS prefix 運(yùn)算符
            prefix運(yùn)算符++和—比它的postfix版本效率更高,因?yàn)楫?dāng)postfix運(yùn)算符被使用的時(shí)候,會(huì)需要一個(gè)臨時(shí)對(duì)象來(lái)保存改變以前的值。對(duì)于基本類型,編譯器會(huì)消除這一份額外的拷貝,但是對(duì)于用戶定義類型,這似乎是不可能的。因此請(qǐng)你盡可能使用prefix運(yùn)算符。

            三. 內(nèi)聯(lián)函數(shù)
            內(nèi)聯(lián)函數(shù)既能夠去除函數(shù)調(diào)用所帶來(lái)的效率負(fù)擔(dān)又能夠保留一般函數(shù)的優(yōu)點(diǎn)。然而,內(nèi)聯(lián)函數(shù)并不是萬(wàn)能藥,在一些情況下,它甚至能夠降低程序的性能。因此在使用的時(shí)候應(yīng)該慎重。
            1.我們先來(lái)看看內(nèi)聯(lián)函數(shù)給我們帶來(lái)的好處:從一個(gè)用戶的角度來(lái)看,內(nèi)聯(lián)函數(shù)看起來(lái)和普通函數(shù)一樣,它可以有參數(shù)和返回值,也可以有自己的作用域,然而它卻不會(huì)引入一般函數(shù)調(diào)用所帶來(lái)的負(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)一些其他的問(wè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ì)付這種情況的辦法是通過(guò)把一個(gè)un-inlined函數(shù)當(dāng)作static來(lái)處理。因此每一份函數(shù)拷貝僅僅在自己的編譯單元中可見,這樣鏈接錯(cuò)誤就解決了,但是在程序中卻會(huì)留下多份函數(shù)拷貝。在這種情況下,程序的性能不但沒有提升,反而增加了編譯和鏈接時(shí)間以及最終可執(zhí)行體的大小。
            但是幸運(yùn)的是,新的C++標(biāo)準(zhǔn)中關(guān)于un-inlined函數(shù)的說(shuō)法已經(jīng)改變。一個(gè)符合標(biāo)準(zhǔn)C++實(shí)現(xiàn)應(yīng)該只生成一份函數(shù)拷貝。然而,要想所有的編譯器都支持這一點(diǎn)可能還需要很長(zhǎng)時(shí)間。
            另外關(guān)于內(nèi)聯(lián)函數(shù)還有兩個(gè)更令人頭疼的問(wèn)題。第一個(gè)問(wèn)題是該如何進(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è)問(wèn)題是當(dāng)內(nèi)聯(lián)函數(shù)被應(yīng)用在代碼庫(kù)的時(shí)候產(chǎn)生。當(dāng)內(nèi)聯(lián)函數(shù)改變的時(shí)候,用戶必須重新編譯他們的代碼以反映這種改變。然而對(duì)于一個(gè)非內(nèi)聯(lián)函數(shù),用戶僅僅需要重新鏈接就可以了。
            這里想要說(shuō)的是,內(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)中有很大的改善,但是仍然還是不那么完善的。一些編譯器能夠足夠的聰明來(lái)指出哪些函數(shù)可以內(nèi)聯(lián)哪些不能,但是,大多數(shù)編譯器就不那么聰明了,因此這就需要我們的經(jīng)驗(yàn)來(lái)判斷。如果內(nèi)聯(lián)函數(shù)不能增強(qiáng)行能,就避免使用它!


            四. 優(yōu)化你的內(nèi)存使用
            通常優(yōu)化都有幾個(gè)方面:更快的運(yùn)行速度,有效的系統(tǒng)資源使用,更小的內(nèi)存使用。一般情況下,代碼優(yōu)化都是試圖在以上各個(gè)方面進(jìn)行改善。重新放置聲明技術(shù)被證明是消除多余對(duì)象的建立和銷毀,這樣既減小了程序的大小又加快了運(yùn)行速度。然而其他的優(yōu)化技術(shù)都是基于一個(gè)方面------更快的速度或者是更小的內(nèi)存使用。有時(shí),這些目標(biāo)是互斥的,壓縮了內(nèi)存的使用往往卻減慢了代碼速度,快速的代碼卻又需要更多的內(nèi)存支持。下面總結(jié)兩種在內(nèi)存使用上的優(yōu)化方法:
            1. Bit Fields
            在C/C++中都可以存取和訪問(wèn)數(shù)據(jù)的最小組成單元:bit。因?yàn)閎it并不是C/C++基本的存取單元,所以這里是通過(guò)犧牲運(yùn)行速度來(lái)減少內(nèi)存和輔助存儲(chǔ)器的空間的使用。注意:一些硬件結(jié)構(gòu)可能提供了特殊的處理器指令來(lái)存取bit,因此bit fields是否影響程序的速度取決于具體平臺(tái)。
            在我們的現(xiàn)實(shí)生活中,一個(gè)數(shù)據(jù)的許多位都被浪費(fèi)了,因?yàn)槟承?yīng)用根本就不會(huì)有那么大的數(shù)據(jù)范圍。也許你會(huì)說(shuō),bit是如此之小,通過(guò)它就能減小存儲(chǔ)空間的使用嗎?的確,在數(shù)據(jù)量很小的情況下不會(huì)看出什么效果,但是在數(shù)據(jù)量驚人的情況下,它所節(jié)省的空間還是能夠讓我們的眼睛為之一亮的。也許你又會(huì)說(shuō),現(xiàn)在內(nèi)存和硬盤越來(lái)越便宜,何苦要費(fèi)半天勁,這省不了幾個(gè)錢。但是還有另外一個(gè)原因一定會(huì)使你信服,那就是數(shù)字信息傳輸。一個(gè)分布式數(shù)據(jù)庫(kù)都會(huì)在不同的地點(diǎn)有多份拷貝。那么數(shù)百萬(wàn)的紀(jì)錄傳輸就會(huì)顯得十分昂貴。Ok,現(xiàn)在我們就來(lái)看看該如何做吧,首先看下面這段代碼:
            struct BillingRec
            {
            long cust_id;
            long timestamp;
            enum CallType
            {
            toll_free,
            local,
            regional,
            long_distance,
            international,
            cellular
            } type;
            enum CallTariff
            {
            off_peak,
            medium_rate,
            peak_time
            } tariff;
            };
            上面這個(gè)結(jié)構(gòu)體在32位的機(jī)器上將會(huì)占用16字節(jié),你會(huì)發(fā)現(xiàn)其中有許多位都被浪費(fèi)了,尤其是那兩個(gè)enum型,浪費(fèi)更是嚴(yán)重,所以請(qǐng)看下面做出的改進(jìn):
            struct BillingRec
            {
            int cust_id: 24; // 23 bits + 1 sign bit
            int timestamp: 24;
            enum CallType
            {//...
            };
            enum CallTariff
            {//...
            };
            unsigned call: 3;
            unsigned tariff: 2;
            };
            現(xiàn)在一個(gè)數(shù)據(jù)從16字節(jié)縮減到了8字節(jié),減少了一半,怎么樣,效果還是顯著的吧:)
            2. Unions
            Unions通過(guò)把兩個(gè)或更多的數(shù)據(jù)成員放置在相同地址的內(nèi)存中來(lái)減少內(nèi)存浪費(fèi),這就要求在任何時(shí)間只能有一個(gè)數(shù)據(jù)成員有效。Union 可以有成員函數(shù),包括構(gòu)造函數(shù)和析構(gòu)函數(shù),但是它不能有虛函數(shù)。C++支持anonymous unions。anonymous union是一個(gè)未命名類型的未命名對(duì)象。例如:
            union { long n; void * p}; // anonymous
            n = 1000L; // members are directly accessed
            p = 0; // n is now also 0
            不像命名的union,它不能有成員函數(shù)以及非public的數(shù)據(jù)成員。
            那么unions什么時(shí)候是有用的呢?下面這個(gè)類從數(shù)據(jù)庫(kù)中獲取一個(gè)人的信息。關(guān)鍵字既可以是一個(gè)特有的ID或者人名,但是二者卻不能同時(shí)有效:
            class PersonalDetails
            {
            private:
            char * name;
            long ID;
            //...
            public:
            PersonalDetails(const char *nm); //key is of type char * used
            PersonalDetails(long id) : ID(id) {} //numeric key used
            };
            上面這段代碼中就會(huì)造成內(nèi)存的浪費(fèi),因?yàn)樵谝粋€(gè)時(shí)間只能有一個(gè)關(guān)鍵字有效。anonymous union可以在這里使用來(lái)減少內(nèi)存的使用,例如:
            class PersonalDetails
            {
            private:
            union //anonymous
            {
            char * name;
            long ID;
            };
            public:
            PersonalDetails(const char *nm);
            PersonalDetails(long id) : ID(id) {/**/} // direct access to a member
            //...
            };
            通過(guò)使用union,PersonalDetails類的大小被減半。但是這里要說(shuō)明的是,節(jié)省4 個(gè)字節(jié)內(nèi)存并不值得引入union所帶來(lái)的麻煩,除非這個(gè)類作為數(shù)百萬(wàn)數(shù)據(jù)庫(kù)記錄的類型或者紀(jì)錄在一條很慢的通信線路傳輸。值得注意的是unions并不引入任何運(yùn)行期負(fù)擔(dān),所以這里不會(huì)有什么速度上的損失。anonymous union的優(yōu)點(diǎn)就是它的成員可以被直接訪問(wèn)。
            五. 速度優(yōu)化
            在一些對(duì)速度要求非常苛刻的應(yīng)用系統(tǒng)中,每一個(gè)CPU周期都是要爭(zhēng)取的。這個(gè)部分展現(xiàn)了一些簡(jiǎn)單方法來(lái)進(jìn)行速度優(yōu)化。
            1. 使用類來(lái)包裹長(zhǎng)的參數(shù)列表
            一個(gè)函數(shù)調(diào)用的負(fù)擔(dān)將會(huì)隨著參數(shù)列表的增長(zhǎng)而增加。運(yùn)行時(shí)系統(tǒng)不得不建立堆棧來(lái)存儲(chǔ)參數(shù)值;通常,當(dāng)參數(shù)很多的時(shí)候,這樣一個(gè)操作就會(huì)花費(fèi)很長(zhǎng)的時(shí)間。
            把參數(shù)列表包裹進(jìn)一個(gè)單獨(dú)的類中并且通過(guò)引用進(jìn)行傳遞,這樣將會(huì)節(jié)省很多的時(shí)間。當(dāng)然,如果函數(shù)本身就很長(zhǎng),那么建立堆棧的時(shí)間就可以忽略了,因此也就沒有必要這樣做。然而,對(duì)于那些執(zhí)行時(shí)間很短而且經(jīng)常被調(diào)用的函數(shù)來(lái)說(shuō),包裹一個(gè)長(zhǎng)的參數(shù)列表在對(duì)象中并且通過(guò)引用傳遞將會(huì)提高性能。
            2. 寄存器變量
            register specifier被用來(lái)告訴編譯器一個(gè)對(duì)象將被會(huì)非常多的使用,可以把它放入寄存器中。例如:
            void f()
            {
            int *p = new int[3000000];
            register int *p2 = p; //store the address in a register
            for (register int j = 0; j<3000000; j++)
            {
            *p2++ = 0;
            }
            //...use p
            delete [] p;
            }
            循環(huán)計(jì)數(shù)是應(yīng)用寄存器變量的最好的候選者。當(dāng)它們沒有被存入一個(gè)寄存器中,大部分的循環(huán)時(shí)間都被用在了從內(nèi)存中取出變量和給變量賦新值上。如果把它存入一個(gè)寄存器中的話,將會(huì)大大減少這種負(fù)擔(dān)。需要注意的是,register specifier僅僅是對(duì)編譯器的一個(gè)建議。就好比內(nèi)聯(lián)函數(shù)一樣,編譯器可以拒絕把一個(gè)對(duì)象存儲(chǔ)到寄存器中。另外,現(xiàn)代的編譯器都會(huì)通過(guò)把變量放入寄存器中來(lái)優(yōu)化循環(huán)計(jì)數(shù)。Register storage specifier并不僅僅局限在基本類型上,它能夠被應(yīng)用于任何類型的對(duì)象。如果對(duì)象太大而不能裝進(jìn)寄存器的話,編譯器仍然能夠把它放入一個(gè)高速存儲(chǔ)器中,例如cache。
            用register storage specifier聲明函數(shù)型參將會(huì)是建議編譯器把實(shí)參存入寄存器中而不是堆棧中。例如:

            void f(register int j, register Date d);

            3. 把那些保持不變的對(duì)象聲明為const
            通過(guò)把對(duì)象聲明為const,編譯器就可以利用這個(gè)聲明把這樣一個(gè)對(duì)象放入寄存器中。
            4. Virtual function的運(yùn)行期負(fù)擔(dān)
            當(dāng)調(diào)用一個(gè)virtual function,如果編譯器能夠解決調(diào)用的靜態(tài)化,將不會(huì)引入額外的負(fù)擔(dān)。另外,一個(gè)非常短的虛函數(shù)可以被內(nèi)聯(lián)處理。在下面這個(gè)例子中,一個(gè)聰明的編譯器能夠做到靜態(tài)調(diào)用虛函數(shù):
            #include <iostream>
            using namespace std;
            class V
            {
            public:
            virtual void show() const { cout<<"I'm V"<<endl; }
            };
            class W : public V
            {
            public:
            void show() const { cout<<"I'm W"<<endl; }
            };
            void f(V & v, V *pV)
            {
            v.show();
            pV->show();
            }
            void g()
            {
            V v;
            f(v, &v);
            }
            int main()
            {
            g();
            return 0;
            }
            如果整個(gè)程序出現(xiàn)在一個(gè)單獨(dú)的編譯單元中,編譯器能夠?qū)ain()中的g()進(jìn)行內(nèi)聯(lián)替換。并且在g()中f()的調(diào)用也能夠被內(nèi)聯(lián)處理。因?yàn)閭鹘of()的參數(shù)的動(dòng)態(tài)類型能夠在編譯期被知曉,因此編譯器能夠把對(duì)虛函數(shù)的調(diào)用靜態(tài)化。但是不能保證每個(gè)編譯器都這樣做。然而,一些編譯器確實(shí)能夠利用在編譯期獲得參數(shù)的動(dòng)態(tài)類型從而使得函數(shù)的調(diào)用在編譯期間就確定了下來(lái),避免了動(dòng)態(tài)綁定的負(fù)擔(dān)。
            5. Function objects VS function pointers
            用function objects取代function pointers的好處不僅僅局限在能夠泛化和簡(jiǎn)單的維護(hù)性上。而且編譯器能夠?qū)unction object的函數(shù)調(diào)用進(jìn)行內(nèi)聯(lián)處理,從而進(jìn)一步的增強(qiáng)了性能
            六. 最后的求助
            迄今為止為大家展示的優(yōu)化技術(shù)并沒有在設(shè)計(jì)以及代碼的可讀性上做出妥協(xié)。事實(shí)上,它們中的一些還提高了軟件的穩(wěn)固性和可維護(hù)性。但是在一些對(duì)時(shí)間和內(nèi)存有嚴(yán)格限制的軟件開發(fā)中,上面的技術(shù)可能還不夠;有可能還需要一些會(huì)影響軟件的可移植性和擴(kuò)展性的技術(shù)。但是這些技術(shù)只能在所有其他的優(yōu)化技術(shù)都被應(yīng)用但是還不符合要求的情況下使用。
            1. 關(guān)閉RTTI和異常處理支持
            當(dāng)你導(dǎo)入純C代碼給C++編譯器的時(shí)候,你可能會(huì)發(fā)現(xiàn)有一些性能上的損失。這并不是語(yǔ)言或者編譯器的錯(cuò)誤,而是編譯器作出的一些調(diào)整。如果你想獲得和C編譯器同樣的性能,那么請(qǐng)關(guān)閉編譯器對(duì)RTTI以及異常處理的支持。為什么會(huì)這樣呢?因?yàn)闉榱酥С諶TTI和異常處理,C++編譯器會(huì)插入額外的代碼。這樣就增加了可執(zhí)行體的大小,從而使得效率有所下降。當(dāng)應(yīng)用純C代碼的時(shí)候,那些額外的代碼是不需要的,所以你可以通過(guò)關(guān)閉來(lái)避免它。
            2. 內(nèi)聯(lián)匯編
            對(duì)時(shí)間要求苛刻的部分可以用本地匯編來(lái)重寫。結(jié)果可能是速度上的顯著提高。然而,這個(gè)方法不能想當(dāng)然的就去實(shí)施,因?yàn)樗鼘⑹沟脤?lái)的修改非常的困難。維護(hù)代碼的程序員可能對(duì)匯編并不了解。如果想要把軟件運(yùn)行于其他平臺(tái)也需要重寫匯編代碼部分。另外,開發(fā)和測(cè)試匯編代碼是一件辛苦的工作,它將花費(fèi)更長(zhǎng)的時(shí)間。
            3. 直接和操作系統(tǒng)進(jìn)行交互
            API函數(shù)可以使你直接與操作系統(tǒng)進(jìn)行交互。有時(shí),直接執(zhí)行一個(gè)系統(tǒng)命令可能會(huì)快許多。出于這個(gè)目的,你可以使用標(biāo)準(zhǔn)函數(shù)system()。例如,在一個(gè)dos/windows系統(tǒng)下,你可以這樣顯示當(dāng)前目錄下的文件:
            #include <cstdlib>
            using namespace std;
            int main()
            {
            system("dir"); //execute the "dir" command
            }
            注意:這里是在速度和可移植性以及可擴(kuò)展性之間做出的折衷。

            posted on 2005-12-29 17:07 夢(mèng)在天涯 閱讀(3116) 評(píng)論(0)  編輯 收藏 引用 所屬分類: CPlusPlus

            公告

            EMail:itech001#126.com

            導(dǎo)航

            統(tǒng)計(jì)

            • 隨筆 - 461
            • 文章 - 4
            • 評(píng)論 - 746
            • 引用 - 0

            常用鏈接

            隨筆分類

            隨筆檔案

            收藏夾

            Blogs

            c#(csharp)

            C++(cpp)

            Enlish

            Forums(bbs)

            My self

            Often go

            Useful Webs

            Xml/Uml/html

            搜索

            •  

            積分與排名

            • 積分 - 1804314
            • 排名 - 5

            最新評(píng)論

            閱讀排行榜

            午夜精品久久久久久| 亚洲伊人久久综合中文成人网| 精品久久久久久无码中文字幕一区| 亚洲av日韩精品久久久久久a| 精品久久8x国产免费观看| 99久久精品九九亚洲精品| 久久人人爽人人爽人人片AV麻烦| 91久久精品91久久性色| 久久九九免费高清视频| 久久精品99久久香蕉国产色戒| 国产成人99久久亚洲综合精品| 国产亚洲精品久久久久秋霞| 99久久国产综合精品网成人影院 | 久久精品这里只有精99品| 精品伊人久久大线蕉色首页| 91精品国产91久久久久久| 亚洲中文字幕久久精品无码喷水| 久久久久夜夜夜精品国产| 亚洲中文字幕久久精品无码APP| 国产巨作麻豆欧美亚洲综合久久| 久久久久久九九99精品| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区 | 国内精品久久久久久麻豆 | 欧洲精品久久久av无码电影| 青青热久久国产久精品 | 久久久黄片| 久久精品国产91久久麻豆自制 | yellow中文字幕久久网| 久久久久久夜精品精品免费啦 | 久久精品亚洲日本波多野结衣 | 91精品国产色综久久| 午夜天堂av天堂久久久| 无码任你躁久久久久久老妇App| 91精品国产高清久久久久久国产嫩草| 久久水蜜桃亚洲av无码精品麻豆| 国内精品人妻无码久久久影院导航| 性高朝久久久久久久久久| 久久亚洲国产精品五月天婷| 久久国产精品二国产精品| 国产精品成人无码久久久久久| 久久99毛片免费观看不卡|