青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

C++ 心得

我們現(xiàn)在編寫一個(gè)程序越來越容易了。利用一些軟件開發(fā)工具,往往只要通過鼠標(biāo)的拖拖點(diǎn)點(diǎn),計(jì)算機(jī)就會(huì)自動(dòng)幫你生成許多代碼。但在很多時(shí)候,計(jì)算機(jī)的這種能力被濫用了,我們往往只考慮把這個(gè)程序搭起來,而不去考慮程序的性能如何,程序是否足夠的健壯。而此節(jié)課的目的主要是介紹一些編碼的經(jīng)驗(yàn),讓大家編寫的程序更加健壯和高性能。


  在C++編程中應(yīng)該盡量使用const和inline來代替#define,盡量做到能不用#define就不用。#define常見的用途有“定義常量”以及“定義宏”,但其中存在諸多的弊病。

  第一,查錯(cuò)不直觀,不利于調(diào)試。Define的定義是由預(yù)處理程序處理的,作的是完全的文本替換,不做任何的類型檢查。在編譯器處理階段,define定義的東西已經(jīng)被完全替換了,這樣在debug的時(shí)候就看不到任何的相關(guān)信息,即跟蹤時(shí)不能step into宏。例如,把ASPECT_RATIO用define定義成1.653,編譯器就看不到ASPECT_RATIO這個(gè)名字了。如果編譯器報(bào)1.653錯(cuò),那么就無從知道此1.653來自于何處。在真正編碼的時(shí)候應(yīng)該使用如下的語句來定義:

static const double ASPECT_RATIO = 1.653;


  第二,沒有任何類型信息,不是type safe。因?yàn)樗俏谋炯?jí)別的替換,這樣不利于程序的維護(hù)。

  第三,define的使用很容易造成污染。比如,如果有兩個(gè)頭文件都定義了ASPECT_RATIO, 而一個(gè)CPP文件又同時(shí)包含了這兩個(gè)頭文件,那么就會(huì)造成沖突。更難查的是另外一種錯(cuò)誤,比如有如下的代碼:

  // in header file def.h
  #define Apple 1
  #define Orange 2
    #define Pineapple 3
   …
  // in some cpp file that includes the def.h
  enum Colors {White, Black, Purple, Orange};


  在.h文件中Orange被定義成水果的一種,而在.cpp文件中Orange又成為了一種顏色,那么編譯器就會(huì)把此處的Orange替換成2,編譯可能仍然可以通過,程序也能夠運(yùn)行,但是這就成了一個(gè)bug,表現(xiàn)出古怪的錯(cuò)誤,且很難查錯(cuò)。再比如定義了一個(gè)求a與b哪個(gè)數(shù)大的宏,#define max(a,b) ((a) > (b) ? (a) : (b))

  int a = 5, b = 0;
  max(++ a, b);
  max(++ a, b + 10);

190-823 117-202 
  在上面的操作中,max(++ a, b); 語句中a被++了兩次,而max(++ a, b + 10); 語句中a只加了一次,這樣在程序處理中就很有可能成為一個(gè)bug,且此bug也非常的難找。在實(shí)際編碼時(shí)可以使用如下的語句來做:

  template<class T>
  inline const T&
  max(const T& a, const T& b) { return a > b ? a : b; }


  2、Prefer C++-style casts

  在程序中經(jīng)常會(huì)需要把一種類型轉(zhuǎn)換成另外一種類型,在C++中應(yīng)該使用static_cast、const_cast、dynamic_cast、reinterpret_cast關(guān)鍵字來做類型轉(zhuǎn)換。因?yàn)檫@有以下好處,一是其本身就是一種注釋,在代碼中看到上面這些關(guān)鍵字就可馬上知道此處是進(jìn)行類型轉(zhuǎn)換。二是C語言中類型轉(zhuǎn)換通常是很難進(jìn)行搜索的,而通過關(guān)鍵字cast則可以很容易的找到程序中出現(xiàn)類型轉(zhuǎn)換的地方了。

  3、Distinguish between prefix and postfix forms of increment and decrement operators

  通常對于操作系統(tǒng)或編譯器自身支持的類型,prefix(前綴,如++i)與postfix(后綴,如i++)的效果是一樣的。因?yàn)楝F(xiàn)在的編譯器都很聰明,它會(huì)自動(dòng)做優(yōu)化,這兩者的匯編代碼是一樣的,性能不會(huì)有差別。但有時(shí)候也會(huì)有不同的,如一些重載了操作符的類型。下面是模擬prefix與postfix的操作過程,可以發(fā)現(xiàn)在postfix操作中會(huì)生成一個(gè)臨時(shí)變量,而這一臨時(shí)變量是會(huì)占用額外的時(shí)間和開銷的。

  // prefix form: increment and fetch
  UPInt& UPInt::operator++()
   {
    *this += 1; // increment
   return *this; // fetch
   }
  // postfix form: fetch and increment
   const UPInt UPInt::operator++(int)
   {
    UPInt oldValue = *this; // fetch
   ++(*this); // increment
    return oldValue; // return what was fetched
   }


  一般情況下不需要區(qū)分是先++,還是后++,但是我們在編寫程序的時(shí)候最好能習(xí)慣性的將其寫成++i的形式,如在使用STL中的iterator時(shí),prefix與postfix會(huì)有相當(dāng)大的性能差異。請不要小看這些細(xì)節(jié),實(shí)際在編寫程序的時(shí)候,若不注意具體細(xì)節(jié),你會(huì)發(fā)現(xiàn)程序的性能會(huì)非常的低。但要注意,雖然在大多數(shù)情況下可以用prefix來代替postfix,但有一種情況例外,那就是有[]操作符時(shí),比如gzArray [++index] 是不等于 gzArray[index++]的。

4、Minimizing Compile-time Dependencies

  有些人在編寫程序時(shí),往往喜歡將一個(gè).h文件包含到另一個(gè).h文件,而實(shí)踐證明在做大型軟件時(shí)這是一個(gè)非常不好的習(xí)慣,因這樣會(huì)造成很多依賴的問題,包含較多的.h文件,別人又使用了這個(gè)class,而在他的那個(gè)工程中可能并不存在這些.h文件,這樣很可能就編譯不能通過。而且這樣做,還可能造成很難去更新一個(gè)模塊的情況。因?yàn)橐粋€(gè).h文件被很多模塊包含的話,如果修改了此.h文件,在編譯系統(tǒng)的時(shí)候,編譯器會(huì)去尋找哪些模塊依賴于某個(gè)被修改過的.h文件,那么就導(dǎo)致了所有包含入此.h文件的模塊全都要進(jìn)行重新編譯。在項(xiàng)目比較小的時(shí)候,大家可能還感覺不到差別,但是如果說是在大型的軟件系統(tǒng)里,你可能編譯一遍源碼需要七、八個(gè)小時(shí)。如果你這個(gè).h文件被很多模塊包含的話,就算在.h文件中加了一行注釋,在編譯時(shí)編譯器檢查哪些文件被改動(dòng),那么所有包含入此.h文件的模塊都會(huì)被重新編譯,造成巨大的時(shí)間和精力負(fù)擔(dān)。對于此問題,解決的方法就是讓.h文件自包含,也就是說讓它包含盡量少的東西。所謂盡量少是指如刪掉任何一個(gè)它包含進(jìn)來的.h文件,都將無法正常進(jìn)行工作。其實(shí)在很多情況下,并不需要一個(gè).h文件去包含另一個(gè).h文件,完全可以通過class聲明來解決依賴關(guān)系的這種問題。再來看下面這個(gè)例子:1Z0-043

  #include "a.h" // class A
  #include "b.h" // class B
  #include "c.h" // class C
  #include "d.h" // class D
  #include "e.h" // class E
  class X : public A, private B
  {
   public:
  E SomeFunctionCall(E someParameter);
   private:
   D m_dInstance;
  };


  當(dāng)類X從類A和類B中派生時(shí),需要知道X在內(nèi)存中都有哪些data,通常在內(nèi)存中前面是基類的data,后面緊跟的是此派生類自身定義的data,因此就必須知道類A與類B的內(nèi)部細(xì)節(jié),要不然編譯器就無法來安排內(nèi)存了。但是在處理參數(shù)以及參數(shù)返回值的時(shí)候,實(shí)際上并不需要知道這些信息,在此處定義的SomeFunctionCall()只需知道E是個(gè)class就足夠了,并不需要知道類E中的data如長度等的具體細(xì)節(jié)。上面的代碼應(yīng)該改寫成如下的形式,以減少依賴關(guān)系:

  #include "a.h" // class A
  #include "b.h" // class B
  #include "c.h" // class C
  #include "d.h" // class D
  class E;
  class X : public A, private B
  {
   public:
  E SomeFunctionCall(E someParameter);
   private:
  D m_dInstance;
  };


  5、Never treat arrays polymorphically

  不要把數(shù)組和多態(tài)一起使用,請看下面的例子。

  class BST { ... };
  class BalancedBST: public BST { ... };
  void printBSTArray(ostream& s, const BST array[], int numElements)
  {
  for (int i = 0; i < numElements; ++i)
  {
   s << array[i];
  // this assumes an operator<< is defined for BST
  }
  }

  BalancedBST bBSTArray[10];
  printBSTArray(cout, bBSTArray, 10);


  數(shù)組在內(nèi)存中是一個(gè)連續(xù)的內(nèi)存空間,而在數(shù)組中應(yīng)該如何來定位一個(gè)元素呢?過程是這樣的,編譯器可以知道每個(gè)數(shù)據(jù)類型的長度大小,如果數(shù)組的index是0,則會(huì)自動(dòng)去取第一個(gè)元素;如果是指定了某個(gè)index,編譯器則會(huì)根據(jù)此index與該數(shù)據(jù)類型的長度自動(dòng)去算出該元素的位置。

  在printBSTArray()函數(shù)中,盡管傳入的參數(shù)是BalancedBST類型,但由于其本來定義的類型是BST,那么它依然會(huì)根據(jù)BST來計(jì)算類型的長度。而通常派生類實(shí)例所占的內(nèi)存要比基類實(shí)例所占的內(nèi)存大一些,因此該程序在編譯時(shí)會(huì)報(bào)錯(cuò)。請記住,永遠(yuǎn)不要把數(shù)組和C++的多態(tài)性放在一起使用。

  6、Prevent exceptions from leaving destructors

  析構(gòu)函數(shù)中一定不要拋出異常。通常有兩種情況會(huì)導(dǎo)致析構(gòu)函數(shù)的調(diào)用,一種是當(dāng)該類的對象離開了它的域,或delete表達(dá)式中一個(gè)該類對象的指針,另一種是由于異常而引起析構(gòu)函數(shù)的調(diào)用。

  如果析構(gòu)函數(shù)被調(diào)用是由于exception引起,而此時(shí)在析構(gòu)函數(shù)中又拋出了異常,程序會(huì)立即被系統(tǒng)終止,甚至都來不及進(jìn)行內(nèi)存釋放。因此如果在析構(gòu)函數(shù)中拋出異常的話,就很容易混淆引起異常的原因,且這樣的軟件也會(huì)讓用戶非常惱火。由于析構(gòu)函數(shù)中很可能會(huì)調(diào)用其它的一些函數(shù),所以在寫析構(gòu)函數(shù)的時(shí)候一定要注意,對這些函數(shù)是否會(huì)拋出異常要非常清楚,如果會(huì)的話,就一定要小心了。比如下面這段代碼:

  Session::~Session()
  {
  logDestruction(this);
  }


  比如logDestruction()函數(shù)可能會(huì)拋出異常,那么我們就應(yīng)該采用下面這種代碼的形式:

  Session::~Session()
  {
   try
  {
   logDestruction(this);
   }
   catch (...)
  {
   }
 }


  這樣程序出錯(cuò)的時(shí)候不會(huì)被立即關(guān)掉,可以給用戶一些其它的選擇,至少先讓他把目前在做的工作保存下來。

  7、Optimization:Remember the 80-20 rule

  在軟件界有一個(gè)20-80法則,其實(shí)這是一個(gè)很有趣的現(xiàn)象,比如一個(gè)程序中20%的代碼使用了該程序所占資源的80%;一個(gè)程序中20%的代碼占用了總運(yùn)行時(shí)間的80%;一個(gè)程序中20%的代碼使用了該程序所占內(nèi)存的80%;在20%的代碼上面需要花費(fèi)80%的維護(hù)力量,等等。這個(gè)規(guī)律還可以被繼續(xù)推廣下去,不過這個(gè)規(guī)律無法被證明,它是人們在實(shí)踐中觀察得出的結(jié)果。從這個(gè)規(guī)律出發(fā),我們在做程序優(yōu)化的時(shí)候,就有了針對性。比如想提高代碼的運(yùn)行速度,根據(jù)這個(gè)規(guī)律可以知道其中20%的代碼占用了80%的運(yùn)行時(shí)間,因此我們只要找到這20%的代碼,并進(jìn)行相應(yīng)的優(yōu)化,那么我們程序的運(yùn)行速度就可以有較大的提高。再如有一個(gè)函數(shù),占用了程序80%的運(yùn)行時(shí)間,如果把這個(gè)函數(shù)的執(zhí)行速度提高10倍,那么對程序整體性能的提高,影響是非常巨大的。如果有一個(gè)函數(shù)運(yùn)行時(shí)間只占總時(shí)間的1%,那就算把這個(gè)函數(shù)的運(yùn)行速度提高1000倍,對程序整體性能的提高也是影響不大的。所以我們的基本思想就是找到占用運(yùn)行時(shí)間最大的那個(gè)函數(shù),然后去優(yōu)化它,哪怕只是改進(jìn)了一點(diǎn)點(diǎn),程序的整體性能也可以被提高很多。

  要想找出那20%的代碼,我們的方法就是使用Profiler,它實(shí)際上是一些公司所開發(fā)的工具,可以檢查程序中各個(gè)模塊所分配內(nèi)存的使用情況,以及每個(gè)函數(shù)所運(yùn)行的時(shí)間等。常見的Profiler有Intel公司開發(fā)的VTune,微軟公司開發(fā)的Visual Studio profiler,DevPartner from Compuware等

posted on 2008-01-11 16:05 lovetiffany 閱讀(1191) 評論(8)  編輯 收藏 引用

評論

# re: C++ 心得 2008-01-11 18:23 TheAnswer

hoho 都是從Scott Meyers的書上援引的吧

static const double ASPECT_RATIO = 1.653;
這句中的static是多余的,const默認(rèn)就是內(nèi)部鏈接的 :)
  回復(fù)  更多評論   

# re: C++ 心得 2008-01-11 18:41 <a href=http://minidx.com>minidxer</a>

這里吧?
http://computer.stuun.cn/erjikaoshi/VC/118170256526290.html  回復(fù)  更多評論   

# re: C++ 心得 2009-06-11 17:54 sunceenjoy

多余嗎?這是防止跟其他文件沖突!!  回復(fù)  更多評論   

# re: C++ 心得 2011-11-23 21:42 pheromone perfume

那么對程序整體性能的提高,影響是非常巨大的。如果有一個(gè)函數(shù)運(yùn)行  回復(fù)  更多評論   

# re: C++ 心得 2011-12-17 15:40 hemorrhoids cure

“向下轉(zhuǎn)換是從一般到一個(gè)更具體的類型的鑄造,即鑄造的層次結(jié)構(gòu):”我得到這個(gè) defination,但仍然不適合我明確  回復(fù)  更多評論   

# re: C++ 心得 2011-12-17 15:44 cellulite treatment

作為一個(gè)正常function.But的,我們可以重載賦值運(yùn)算符,我們不能重載賦值運(yùn)算符作為友元函數(shù)為什麼呢?  回復(fù)  更多評論   

# re: C++ 心得 2011-12-17 15:47 gout cure

C ++繼續(xù)使用和開發(fā)專業(yè)應(yīng)用首選的編程語言之一。  回復(fù)  更多評論   

# re: C++ 心得 2012-01-03 18:50 Slots Canada

C ++也使用硬件設(shè)計(jì),設(shè)計(jì)是最初描述的C ++然後進(jìn)行分析,體系結(jié)構(gòu)的限制  回復(fù)  更多評論   


只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


<2012年10月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

導(dǎo)航

統(tǒng)計(jì)

常用鏈接

留言簿(4)

隨筆檔案

網(wǎng)站收藏

搜索

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            中文亚洲视频在线| 欧美日韩国产成人在线观看| 久久精精品视频| 久久狠狠久久综合桃花| 一区二区三区日韩| 野花国产精品入口| 亚洲一区二区三区成人在线视频精品| 亚洲欧美日韩一区二区三区在线观看| 亚洲精选大片| 欧美午夜大胆人体| 欧美日韩精品一区| 国产精品av久久久久久麻豆网| 欧美精品日本| 国产精品久久久久久亚洲毛片| 国产精品久久999| 国产综合久久久久久鬼色| 国产一区二区三区自拍| 亚洲第一网站免费视频| 欧美激情综合在线| 欧美在线免费播放| 久久综合导航| 国产精品毛片在线| 亚洲精选一区二区| 久久激情综合| 国产精品99久久久久久www| 久久永久免费| 韩国三级电影久久久久久| 一本色道精品久久一区二区三区 | 欧美.www| 国产精品一二| 亚洲三级电影全部在线观看高清| 亚洲一区二区三区777| 欧美风情在线| 老司机久久99久久精品播放免费 | 欧美影院视频| 国产精品亚洲一区| 亚洲女优在线| 亚洲欧美日韩一区二区三区在线| 欧美成人午夜激情视频| 欧美国产一区二区在线观看 | 欧美成人伊人久久综合网| 香港久久久电影| 国产亚洲精品aa| 久久久久久综合| 欧美中文在线免费| 国内成+人亚洲+欧美+综合在线| 亚洲欧美日韩国产成人精品影院| 亚洲国产天堂久久综合网| 久久手机免费观看| 亚洲人成在线播放| 亚洲免费观看高清完整版在线观看| 欧美激情乱人伦| 亚洲欧美一区二区三区极速播放| 99视频+国产日韩欧美| 国产精品日日摸夜夜摸av| 久久综合精品国产一区二区三区| 久久久999国产| 亚洲一区在线播放| 久久精品99国产精品日本| 亚洲人成在线播放| 欧美资源在线观看| 亚洲尤物视频网| 理论片一区二区在线| 亚洲欧美日韩天堂| 久久婷婷成人综合色| 亚洲一区二区在线免费观看| 久久九九有精品国产23| 亚洲欧美影音先锋| 欧美日韩国产三区| 亚洲国产一区二区三区高清| 国产精品免费看久久久香蕉| 亚洲国产综合在线看不卡| 亚洲国产成人不卡| 欧美一区二区高清| 国内精品嫩模av私拍在线观看 | 久久久久久久精| 欧美视频在线观看 亚洲欧| 亚洲福利一区| 亚洲国产综合在线看不卡| 久久亚洲视频| 亚洲区在线播放| 999在线观看精品免费不卡网站| 美女日韩欧美| 日韩一级大片在线| 午夜欧美精品久久久久久久| 国产精品www994| 亚洲欧美日本在线| 免费久久99精品国产自在现线| 韩国美女久久| 欧美日本一区二区视频在线观看| 亚洲精选在线观看| 久久久久国产精品厨房| 狠狠色伊人亚洲综合网站色| 久久久久久日产精品| 亚洲欧洲在线视频| 久久国产高清| 亚洲一区在线播放| 亚洲激精日韩激精欧美精品| 国产精品久久久久免费a∨| 久久精品综合网| 亚洲免费一在线| 亚洲国产福利在线| 久久婷婷丁香| 久久国产黑丝| 久久精品国产成人| 99热免费精品| 亚洲精品日韩激情在线电影| 国产伦精品一区二区三区在线观看 | 亚洲天堂免费观看| 欧美日韩视频一区二区| 蜜臀99久久精品久久久久久软件| 一区二区欧美日韩| 一区二区三区国产在线| 欧美激情乱人伦| 欧美护士18xxxxhd| 欧美成人午夜免费视在线看片| 久久久免费观看视频| 久久精品视频va| 欧美成年人视频| 亚洲成人直播| 亚洲日韩欧美视频一区| 亚洲综合国产| 久久久精品一区二区三区| 久久国产精品久久久| 在线观看中文字幕不卡| 久久精品人人做人人爽| 久久久精品午夜少妇| 亚洲精品免费在线播放| 麻豆久久精品| 久久成人久久爱| 国产精品手机视频| 国产精品s色| 性欧美xxxx视频在线观看| 欧美在线视屏| 亚洲美女视频| 国产一区二区精品丝袜| 亚洲专区一区二区三区| 久久国产精品久久久久久久久久| 能在线观看的日韩av| 欧美一区国产在线| 亚洲一线二线三线久久久| 亚洲片国产一区一级在线观看| 亚洲美女色禁图| 久久精品一区二区三区四区| 亚洲九九爱视频| 亚洲欧美视频在线观看视频| 欧美88av| 欧美一区二区三区播放老司机| 欧美国产亚洲另类动漫| 在线成人亚洲| 免费观看欧美在线视频的网站| 一区二区三区高清视频在线观看| 欧美一区成人| 欧美日韩高清在线一区| 亚洲二区视频| 日韩视频一区二区三区| 中文日韩欧美| 六月丁香综合| 久久一区激情| 亚洲毛片一区| 99热这里只有精品8| 国产精品久久久一区二区| 亚洲一区免费观看| 亚洲综合欧美| 亚洲高清在线| 日韩天堂在线观看| 国产日韩精品一区二区三区在线| 欧美一区亚洲| 久久这里只有精品视频首页| 亚洲国产精品久久精品怡红院| 欧美www视频在线观看| 欧美日韩另类综合| 欧美中日韩免费视频| 久久久久久久综合色一本| 精品999日本| 亚洲精品欧美日韩专区| 国产美女精品人人做人人爽| 久久综合网hezyo| 国产精品色婷婷久久58| 欧美综合国产精品久久丁香| 麻豆精品在线视频| 久久久久九九九| 欧美日韩黄视频| 欧美aa在线视频| 黄色一区二区在线观看| 99精品视频免费全部在线| 国精品一区二区| 先锋影音国产一区| 亚洲欧美日韩成人高清在线一区| 久久久亚洲精品一区二区三区| 久久亚洲不卡| 久久亚洲综合色| 国产精品区一区二区三| 亚洲日本一区二区三区| 亚洲高清在线观看| 欧美承认网站| 一区二区激情视频| 亚洲一区二区三区免费在线观看| 欧美高清影院| 99re6热在线精品视频播放速度|