亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

提高C++程序運行效率的10個簡單方法

2019-11-06 06:14:00
字體:
來源:轉載
供稿:網友
本文以C/C++程序為例講述了程序運行效率的10個簡單方法,分享給大家供大家參考之用。具體分析如下:

對于每一個程序員來說,程序的運行效率都是一個值得重視,并為之付出努力的問題。但是程序性能的優化也是一門復雜的學問,需要很多的知識,然而并不是每個程序員都具備這樣的知識,而且論述如何優化程序提高程序運行效率的書籍也很少。但是這并不等于我們可以忽略程序的運行效率,下面就介紹一下本人積累的一些簡單實用的提高程序運行效率的方法,希望對大家有所幫助。

一、盡量減少值傳遞,多用引用來傳遞參數。 至于其中的原因,相信大家也很清楚,如果參數是int等語言自定義的類型可能能性能的影響還不是很大,但是如果參數是一個類的對象,那么其效率問題就不言而喻了。例如一個判斷兩個字符串是否相等的函數,其聲明如下:

bool Compare(string s1, string s2)bool Compare(string *s1, string *s2)bool Compare(string &s1, string &s2)bool Compare(const string &s1, const string &s2)

其中若使用第一個函數(值傳遞),則在參數傳遞和函數返回時,需要調用string的構造函數和析構函數兩次(即共多調用了四個函數),而其他的三個函數(指針傳遞和引用傳遞)則不需要調用這四個函數。因為指針和引用都不會創建新的對象。如果一個構造一個對象和析構一個對象的開銷是龐大的,這就是會效率造成一定的影響。

然而在很多人的眼中,指針是一個惡夢,使用指針就意味著錯誤,那么就使用引用吧!它與使用普通值傳遞一樣方便直觀,同時具有指針傳遞的高效和能力。因為引用是一個變量的別名,對其操作等同于對實際對象操作,所以當你確定在你的函數是不會或不需要變量參數的值時,就大膽地在聲明的前面加上一個const吧,就如最后的一個函數聲明一樣。 同時加上一個const還有一個好處,就是可以對常量進行引用,若不加上const修飾符,引用是不能引用常量的。

二、++i和i++引申出的效率問題 看了上面的第一點,你可能覺得,那不就是多調用了四個函數而已,你可能對此不屑一顧。那么來看看下面的例子,應該會讓你大吃一驚。 至于整型變量的前加和后加的區別相信大家也是很清楚的。然而在這里我想跟大家談的卻是C++類的運算符重載,為了與整形變量的用法一致,在C++中重載運算符++時一般都會把前加和后加都重載。你可能會說,你在代碼中不會重載++運算符,但是你敢說你沒有使用過類的++運算符重載嗎?迭代器類你總使用過吧!可能到現在你還不是很懂我在說什么,那么就先看看下面的例子吧,是本人為鏈表寫的一個內部迭代器。

_SingleList::Iterator& _SingleList::Iterator::Operator++()//前加{ pNote = pNote->pNext; return *this;}_SingleList::Iterator _SingleList::Iterator::operator++(int)//后加{ Iterator tmp(*this); pNote = pNote->pNext; return tmp;}

從后加的實現方式可以知道,對象利用自己創建一個臨時對象(自己在函數調用的一個復制),然后改變自己的狀態,并返回這個臨時對象,而前加的實現方式時,直接改變自己的內部狀態,并返回自己的引用。 從第一點的論述可以知道后加實現時會調用復制構造函數,在函數返回時還要調用析構函數,而由于前加實現方式直接改變對象的內部狀態,并返回自己的引用,至始至終也沒有創建新的對象,所以也就不會調用構造函數和析構函數。 然而更加糟糕的是,迭代器通常是用來遍歷容器的,它大多應用在循環中,試想你的鏈表有100個元素,用下面的兩種方式遍歷:

for(_SingleList::Iterator it = list.begin(); it != list.end(); ++it){ //do something} for(_SingleList::Iterator it = list.begin(); it != list.end(); it++){ //do something}

如果你的習慣不好,寫了第二種形式,那么很不幸,做同樣的事情,就是因為一個前加和一個后加的區別,你就要調用多200個函數,其對效率的影響可就不可忽視了。

三、循環引發的討論1(循環內定義,還是循環外定義對象) 請看下面的兩段代碼: 代碼1:

ClassTest CT;for(int i = 0; i < 100; ++i){ CT = a; //do something}

代碼2:

for(int i = 0; i < 100; ++i){ ClassTest CT = a; //do something}

你會覺得哪段代碼的運行效率較高呢?代碼1科學家是代碼2?其實這種情況下,哪段代碼的效率更高是不確定的,或者說是由這個類ClassTest本向決定的,分析如下: 對于代碼1:需要調用ClassTest的構造函數1次,賦值操作函數(operator=)100次;對于代碼2:需要高用(復制)構造函數100次,析構函數100次。 如果調用賦值操作函數的開銷比調用構造函數和析構函數的總開銷小,則第一種效率高,否則第二種的效率高。

四、循環引發的討論2(避免過大的循環) 現在請看下面的兩段代碼, 代碼1:

for(int i = 0; i < n; ++i){ fun1(); fun2();}

代碼2:

for(int i = 0; i < n; ++i){ fun1();}for(int i = 0; i < n; ++i){ fun2();}注:這里的fun1()和fun2()是沒有關聯的,即兩段代碼所產生的結果是一樣的。

以代碼的層面上來看,似乎是代碼1的效率更高,因為畢竟代碼1少了n次的自加運算和判斷,畢竟自加運算和判斷也是需要時間的。但是現實真的是這樣嗎? 這就要看fun1和fun2這兩個函數的規模(或復雜性)了,如果這多個函數的代碼語句很少,則代碼1的運行效率高一些,但是若fun1和fun2的語句有很多,規模較大,則代碼2的運行效率會比代碼1顯著高得多??赡苣悴幻靼走@是為什么,要說是為什么這要由計算機的硬件說起。 由于CPU只能從內存在讀取數據,而CPU的運算速度遠遠大于內存,所以為了提高程序的運行速度有效地利用CPU的能力,在內存與CPU之間有一個叫Cache的存儲器,它的速度接近CPU。而Cache中的數據是從內存中加載而來的,這個過程需要訪問內存,速度較慢。 這里先說說Cache的設計原理,就是時間局部性和空間局部性。時間局部性是指如果一個存儲單元被訪問,則可能該單元會很快被再次訪問,這是因為程序存在著循環??臻g局部性是指如果一個儲存單元被訪問,則該單元鄰近的單元也可能很快被訪問,這是因為程序中大部分指令是順序存儲、順序執行的,數據也一般也是以向量、數組、樹、表等形式簇聚在一起的。 看到這里你可能已經明白其中的原因了。沒錯,就是這樣!如果fun1和fun2的代碼量很大,例如都大于Cache的容量,則在代碼1中,就不能充分利用Cache了(由時間局部性和空間局部性可知),因為每循環一次,都要把Cache中的內容踢出,重新從內存中加載另一個函數的代碼指令和數據,而代碼2則更很好地利用了Cache,利用兩個循環語句,每個循環所用到的數據幾乎都已加載到Cache中,每次循環都可從Cache中讀寫數據,訪問內存較少,速度較快,理論上來說只需要完全踢出fun1的數據1次即可。

五、局部變量VS靜態變量 很多人認為局部變量在使用到時才會在內存中分配儲存單元,而靜態變量在程序的一開始便存在于內存中,所以使用靜態變量的效率應該比局部變量高,其實這是一個誤區,使用局部變量的效率比使用靜態變量要高。 這是因為局部變量是存在于堆棧中的,對其空間的分配僅僅是修改一次esp寄存器的內容即可(即使定義一組局部變量也是修改一次)。而局部變量存在于堆棧中最大的好處是,函數能重復使用內存,當一個函數調用完畢時,退出程序堆棧,內存空間被回收,當新的函數被調用時,局部變量又可以重新使用相同的地址。當一塊數據被反復讀寫,其數據會留在CPU的一級緩存(Cache)中,訪問速度非???。而靜態變量卻不存在于堆棧中。 可以說靜態變量是低效的。

六、避免使用多重繼承 在C++中,支持多繼承,即一個子類可以有多個父類。書上都會跟我們說,多重繼承的復雜性和使用的困難,并告誡我們不要輕易使用多重繼承。其實多重繼承并不僅僅使程序和代碼變得更加復雜,還會影響程序的運行效率。 這是因為在C++中每個對象都有一個this指針指向對象本身,而C++中類對成員變量的使用是通過this的地址加偏移量來計算的,而在多重繼承的情況下,這個計算會變量更加復雜,從而降低程序的運行效率。而為了解決二義性,而使用虛基類的多重繼承對效率的影響更為嚴重,因為其繼承關系更加復雜和成員變量所屬的父類關系更加復雜。

七、盡量少使用dynamic_cast dynamic_cast的作用是進行指針或引用的類型轉換,dynamic_cast的轉換需要目標類型和源對象有一定的關系:繼承關系。 實現從子類到基類的指針轉換,實際上這種轉換是非常低效的,對程序的性能影響也比較大,不可大量使用,而且繼承關系越復雜,層次越深,其轉換時間開銷越大。在程序中應該盡量減少使用。

八、減少除法運算的使用 無論是整數還是浮點數運算,除法都是一件運算速度很慢的指令,在計算機中實現除法是比較復雜的。所以要減少除法運算的次數,下面介紹一些簡單方法來提高效率: 1、通過數學的方法,把除法變為乘法運算,如if(a > b/c),如果a、b、c都是正數,則可寫成if(a*c > b) 2、讓編譯器有優化的余地,如里你要做的運算是int型的n/8的話,寫成(unsigned)n/8有利于編譯器的優化。而要讓編譯器有優化的余地,則除數必須為常數,而這也可以用const修飾一個變量來達到目的。

九、將小粒度函數聲明為內聯函數(inline) 正如我們所知,調用函數是需要保護現場,為局部變量分配內存,函數結束后還要恢復現場等開銷,而內聯函數則是把它的代碼直接寫到調用函數處,所以不需要這些開銷,但會使程序的源代碼長度變大。 所以若是小粒度的函數,如下面的Max函數,由于不需要調用普通函數的開銷,所以可以提高程序的效率。

int Max(int a, int b){ return a>b?a:b;}

十、多用直接初始化 與直接初始化對應的是復制初始化,什么是直接初始化?什么又是復制初始化?舉個簡單的例子,

ClassTest ct1;ClassTest ct2(ct1); //直接初始化ClassTest ct3 = ct1; //復制初始化

那么直接初始化與復制初始化又有什么不同呢?直接初始化是直接以一個對象來構造另一個對象,如用ct1來構造ct2,復制初始化是先構造一個對象,再把另一個對象值復制給這個對象,如先構造一個對象ct3,再把ct1中的成員變量的值復制給ct3,從這里,可以看出直接初始化的效率更高一點,而且使用直接初始化還是一個好處,就是對于不能進行復制操作的對象,如流對象,是不能使用賦值初始化的,只能進行直接初始化??赡芪艺f得不太清楚,那么下面就引用一下經典吧! 以下是PRimer是的原話: “當用于類類型對象時,初始化的復制形式和直接形式有所不同:直接初始化直接調用與實參匹配的構造函數,復制初始化總是調用復制構造函數。復制初始化首先使用指定構造函數創建一個臨時對象,然后用復制構造函數將那個臨時對象復制到正在創建的對象”,還有一段這樣說,“通常直接初始化和復制初始化僅在低級別優化上存在差異,然而,對于不支持復制的類型,或者使用非explicit構造函數的時候,它們有本質區別:

ifstream file1("filename")://ok:direct initializationifstream file2 = "filename";//error:copy constructor is private

注:如還對直接初始化和復制初始化有疑問,可以參考一下前面的一篇文章: C++直接初始化與復制初始化的區別深入解析,里面有有關直接初始化和復制初始化的詳細解釋。 補充: 這里只是一點點的建議,雖然說了這么多,但是還是要說一下的就是:要避免不必要的優化,避免不成熟的優化,不成熟的優化的是錯誤的來源,因為編譯器會為你做很多你所不知道的優化。 希望本文所述對提高大家C++程序設計效率能有所幫助。

轉載自:http://www.jb51.net/article/54792.htm

方法補充:

十一、推遲定義本地變量 雖然C語言中標準是將變量統一定義在開頭,但是在C++中最好放棄這種做法,因為這會帶來不必要的開銷,而且費時費力。 定義一個對象變量通常需要調用一次函數(構造函數)。如果一個變量只在某些情況下需要(例如在一個if聲明語句內),僅在其需要的時候定義,這樣,構造函數僅在其被使用的時候調用。 并且,推遲變量的定義會提高程序的效率,增強程序的可讀性,形成更好的可視性。

十二、在一大段內存進行初始化時,盡量使用memset,例如數組的多次初始化

十三、如果程序中cout使用次數很少或只用一次,則可以使用std::cout來節省空間。因為這樣比導入整個命名空間更經濟

十四、對于類的對象返回引用比返回對象的效率要高。 因為不會調用拷貝構造函數,生成臨時對象;但是特別注意臨時對象和局部變量不能返回引用;


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品揄拍500视频| 国产日韩换脸av一区在线观看| 久久久久成人网| 亚洲2020天天堂在线观看| 亚洲欧美日韩精品久久亚洲区| 日本道色综合久久影院| 国产成人精品a视频一区www| 国产精品高清在线| 欧洲中文字幕国产精品| 亚洲国产精品成人va在线观看| 91久久久亚洲精品| 国产91成人video| 欧美精品18videos性欧| 国产精品久久999| 久久精品一本久久99精品| 亚洲综合精品一区二区| 欧美日韩999| 欧美又大又粗又长| 欧美亚洲一区在线| 国产精品视频午夜| 久久久国产视频91| 精品一区二区亚洲| 91久久精品美女高潮| 亚洲国产精品嫩草影院久久| 91精品久久久久久久久久入口| 黄色精品一区二区| 在线观看国产成人av片| 欧美一级电影免费在线观看| 久久久久久久香蕉网| 欧美一区二粉嫩精品国产一线天| 亚洲精品一区二区三区不| 亚洲欧美日韩久久久久久| 成人精品在线视频| 欧美精品www在线观看| 国产成人拍精品视频午夜网站| 国产精品永久免费视频| 亚洲第一福利视频| 国产大片精品免费永久看nba| 国产精品美女无圣光视频| 26uuu另类亚洲欧美日本老年| 国产久一一精品| 亚洲一区二区三区777| 日韩精品中文字幕有码专区| 久久久精品中文字幕| 亚洲精品福利免费在线观看| 午夜精品一区二区三区在线视| 亚洲精品免费网站| 久久久国产精彩视频美女艺术照福利| 91精品国产综合久久香蕉922| 97精品一区二区视频在线观看| www.久久撸.com| 免费99精品国产自在在线| 久久久久久久激情视频| 98精品在线视频| 国产有码一区二区| 黑人巨大精品欧美一区免费视频| 欧美亚洲另类激情另类| 91在线免费观看网站| 日韩在线观看免费高清| 狠狠躁天天躁日日躁欧美| 亚洲国产古装精品网站| 欧美黑人又粗大| 中文字幕在线观看亚洲| 久久久亚洲网站| 日韩免费电影在线观看| 精品中文字幕在线观看| 8090理伦午夜在线电影| 亚洲国产成人在线播放| 日韩欧美国产黄色| 亚洲人精选亚洲人成在线| 国产精品免费一区二区三区都可以| …久久精品99久久香蕉国产| 亚洲国产欧美一区二区三区同亚洲| 中国china体内裑精亚洲片| 国产欧美一区二区三区久久| 国产91网红主播在线观看| 亚洲欧美在线免费观看| 在线观看亚洲视频| 欧美日韩午夜视频在线观看| 午夜精品久久久久久久久久久久久| 亚洲资源在线看| 久久成人这里只有精品| 欧美尺度大的性做爰视频| 国产精品视频久久久久| 狠狠久久亚洲欧美专区| 国内偷自视频区视频综合| 国产精品午夜一区二区欲梦| 色爱精品视频一区| 久久中国妇女中文字幕| 91精品国产网站| 中文字幕av一区| 亚洲国产小视频在线观看| 亚洲网站在线播放| 日韩精品在线播放| 欧美日韩中国免费专区在线看| 欧美激情三级免费| 一区二区日韩精品| 国产亚洲欧洲黄色| 大伊人狠狠躁夜夜躁av一区| 亚洲黄色av网站| 日韩久久精品成人| 国产成人免费91av在线| 欧美一级黑人aaaaaaa做受| 高清在线视频日韩欧美| 992tv在线成人免费观看| 亚洲天堂一区二区三区| 5252色成人免费视频| 一区二区三区久久精品| 亚洲成人网久久久| 欧美性xxxxxxx| 538国产精品一区二区免费视频| 日韩欧美aⅴ综合网站发布| 在线午夜精品自拍| 欧美在线一区二区三区四| 亚洲高清久久网| 欧美一级大片视频| 欧美精品激情blacked18| 国产精品吴梦梦| 日韩亚洲欧美中文高清在线| 欧美在线视频在线播放完整版免费观看| 97视频在线观看免费高清完整版在线观看| 国产玖玖精品视频| 国产精品av在线| 国产精品高精视频免费| 欧美色道久久88综合亚洲精品| 国产精品一区二区三区久久| 国产成人精品在线| 精品久久久久人成| 欧美日韩国产页| 国产精品日韩久久久久| 欧美日韩成人黄色| 国产精品久久久久久久久久久久久| 亚洲精品中文字幕女同| 日韩av免费网站| 成人中文字幕+乱码+中文字幕| 久久夜精品va视频免费观看| 国产成+人+综合+亚洲欧美丁香花| 精品久久久久久亚洲国产300| 97视频在线观看网址| 久久99热这里只有精品国产| 久久中国妇女中文字幕| 国产主播在线一区| 欧美大片免费观看| 最近2019中文字幕第三页视频| 国产精品久久不能| 欧美日韩激情小视频| 亚洲国产精彩中文乱码av| 国产精品自拍偷拍视频| 国产精品第一视频| 中日韩美女免费视频网址在线观看| 欧美丰满片xxx777| 亚洲欧美激情四射在线日| 久久综合电影一区| 欧美高清电影在线看| 亚洲精品福利免费在线观看| 91色琪琪电影亚洲精品久久| 亚洲国产成人精品一区二区| 美女视频久久黄| 欧美精品videossex88| 亚洲欧美国产日韩天堂区| 精品亚洲一区二区三区在线播放| 久久久久久一区二区三区| 538国产精品一区二区免费视频| 国产在线视频欧美|