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

C++ 心得

我們現在編寫一個程序越來越容易了。利用一些軟件開發工具,往往只要通過鼠標的拖拖點點,計算機就會自動幫你生成許多代碼。但在很多時候,計算機的這種能力被濫用了,我們往往只考慮把這個程序搭起來,而不去考慮程序的性能如何,程序是否足夠的健壯。而此節課的目的主要是介紹一些編碼的經驗,讓大家編寫的程序更加健壯和高性能。


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

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

static const double ASPECT_RATIO = 1.653;


  第二,沒有任何類型信息,不是type safe。因為它是文本級別的替換,這樣不利于程序的維護。

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

  // 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又成為了一種顏色,那么編譯器就會把此處的Orange替換成2,編譯可能仍然可以通過,程序也能夠運行,但是這就成了一個bug,表現出古怪的錯誤,且很難查錯。再比如定義了一個求a與b哪個數大的宏,#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只加了一次,這樣在程序處理中就很有可能成為一個bug,且此bug也非常的難找。在實際編碼時可以使用如下的語句來做:

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


  2、Prefer C++-style casts

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

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

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

  // 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
   }


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

4、Minimizing Compile-time Dependencies

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


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

  #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

  不要把數組和多態一起使用,請看下面的例子。

  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);


  數組在內存中是一個連續的內存空間,而在數組中應該如何來定位一個元素呢?過程是這樣的,編譯器可以知道每個數據類型的長度大小,如果數組的index是0,則會自動去取第一個元素;如果是指定了某個index,編譯器則會根據此index與該數據類型的長度自動去算出該元素的位置。

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

  6、Prevent exceptions from leaving destructors

  析構函數中一定不要拋出異常。通常有兩種情況會導致析構函數的調用,一種是當該類的對象離開了它的域,或delete表達式中一個該類對象的指針,另一種是由于異常而引起析構函數的調用。

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

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


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

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


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

  7、Optimization:Remember the 80-20 rule

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

  要想找出那20%的代碼,我們的方法就是使用Profiler,它實際上是一些公司所開發的工具,可以檢查程序中各個模塊所分配內存的使用情況,以及每個函數所運行的時間等。常見的Profiler有Intel公司開發的VTune,微軟公司開發的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默認就是內部鏈接的 :)
  回復  更多評論   

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

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

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

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

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

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

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

“向下轉換是從一般到一個更具體的類型的鑄造,即鑄造的層次結構:”我得到這個 defination,但仍然不適合我明確  回復  更多評論   

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

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

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

C ++繼續使用和開發專業應用首選的編程語言之一。  回復  更多評論   

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

C ++也使用硬件設計,設計是最初描述的C ++然後進行分析,體系結構的限制  回復  更多評論   


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

導航

統計

常用鏈接

留言簿(4)

隨筆檔案

網站收藏

搜索

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲美女视频在线观看| 亚洲国产精品久久久久秋霞不卡 | 国产伦精品一区二区三区在线观看| 欧美福利专区| 欧美日韩国产小视频在线观看| 欧美激情一区二区三区四区| 欧美成人国产一区二区| 欧美日韩另类在线| 国产精品素人视频| 一区二区在线视频播放| 亚洲日本aⅴ片在线观看香蕉| 亚洲精品国产精品久久清纯直播| 99日韩精品| 久久av红桃一区二区小说| 麻豆freexxxx性91精品| 亚洲精品免费在线观看| 亚洲婷婷在线| 久久久精品国产免大香伊 | 美女黄毛**国产精品啪啪 | 欧美在线免费| 欧美激情一区二区在线| 久久综合中文色婷婷| 99riav国产精品| 亚洲视频一区二区免费在线观看| 欧美一区综合| 欧美丰满高潮xxxx喷水动漫| 国产精品久久久一区二区| 在线观看视频一区二区| 亚洲午夜在线观看| 免费观看不卡av| 亚洲一区二区三区免费视频| 美女露胸一区二区三区| 国产精品一卡二| 妖精成人www高清在线观看| 久久久亚洲国产天美传媒修理工| 亚洲国产精品视频| 欧美一区二区三区视频| 欧美日韩一区二区精品| 亚洲国产精品成人久久综合一区| 性久久久久久久久| 99精品国产热久久91蜜凸| 毛片一区二区| 在线视频成人| 久久伊人免费视频| 欧美亚洲一区在线| 国产精品在线看| 亚洲欧美日韩国产一区二区| 亚洲精品黄网在线观看| 欧美成人一区二区| 亚洲黄色高清| 欧美韩日高清| 麻豆精品视频在线观看视频| 狠狠色狠狠色综合| 久久精品青青大伊人av| 欧美亚洲视频一区二区| 国产欧美日韩一区二区三区在线 | 国产精品va| 一区二区三区国产| 亚洲日本欧美日韩高观看| 免费视频一区| 亚洲人成亚洲人成在线观看图片 | 亚洲欧美视频在线观看视频| 欧美日韩综合不卡| 一本大道久久精品懂色aⅴ| 亚洲国产成人精品女人久久久 | 国产精品久久久久久av下载红粉| 一区二区av| 亚洲美女av在线播放| 欧美剧在线免费观看网站| av成人免费在线| 99热精品在线| 国产精品综合视频| 久久午夜国产精品| 欧美顶级少妇做爰| 美女黄色成人网| 国产精品综合色区在线观看| 欧美日韩成人| 一区二区三区高清不卡| 一区二区三区欧美在线| 国产精品一区二区三区免费观看 | 免费观看成人鲁鲁鲁鲁鲁视频 | 国产香蕉97碰碰久久人人| 久久www成人_看片免费不卡| 欧美在线视频a| 亚洲大胆在线| 日韩视频免费观看高清完整版| 国产精品久久久久久av福利软件 | 欧美v日韩v国产v| 欧美—级高清免费播放| 午夜一级久久| 久久亚洲国产成人| 亚洲网址在线| 久久久999成人| 亚洲另类在线视频| 亚洲主播在线| 亚洲人成亚洲人成在线观看| 一区二区三区av| 一区二区在线看| 亚洲日本va午夜在线电影| 国产精品久久久一区二区| 久久精品天堂| 欧美欧美午夜aⅴ在线观看| 午夜精品久久久久久久99黑人| 午夜精品一区二区三区在线视 | 久久成人精品视频| 欧美成年网站| 欧美一区二区三区另类| 久久一区二区三区国产精品| 在线综合视频| 久久久免费av| 午夜精彩国产免费不卡不顿大片| 久久久久久91香蕉国产| 亚洲午夜一区二区三区| 免费h精品视频在线播放| 欧美在线观看网址综合| 欧美激情性爽国产精品17p| 久久亚洲国产精品一区二区| 欧美日韩一区二区在线播放| 欧美成人精品1314www| 国产麻豆成人精品| 99www免费人成精品| 亚洲国产成人久久综合| 欧美一二三区精品| 午夜精品成人在线| 欧美日韩日韩| 日韩视频在线一区二区| 久久综合伊人77777| 精品成人国产在线观看男人呻吟| 亚洲精选视频免费看| 在线播放视频一区| 亚洲欧美另类在线| 亚洲一区二区三区中文字幕| 欧美激情一区三区| 欧美电影电视剧在线观看| 国产日韩欧美精品在线| 亚洲一区免费网站| 正在播放亚洲一区| 欧美激情亚洲自拍| 亚洲国产精品久久精品怡红院 | 国产精品日韩欧美大师| 亚洲美女免费精品视频在线观看| 亚洲激情视频在线观看| 久久综合综合久久综合| 乱码第一页成人| 精品二区视频| 久久久久久一区二区三区| 久久人人97超碰人人澡爱香蕉| 国产午夜精品理论片a级大结局| 亚洲一区二区三区四区视频| 亚洲一区免费| 国产精品女主播| 亚洲欧美日韩国产一区二区| 欧美一区中文字幕| 国内外成人免费激情在线视频| 久久精品最新地址| 欧美好骚综合网| 日韩视频中文字幕| 欧美午夜大胆人体| 亚洲欧美国产另类| 久久久噜噜噜久噜久久| 伊甸园精品99久久久久久| 美女久久一区| 在线中文字幕一区| 久久久一区二区三区| 亚洲国产另类 国产精品国产免费| 免费观看在线综合色| 99re66热这里只有精品4| 性欧美办公室18xxxxhd| 激情成人av在线| 欧美日韩调教| 欧美一区二区精品| 亚洲国产欧美日韩精品| 亚洲伊人色欲综合网| 国产视频一区欧美| 快射av在线播放一区| 亚洲另类在线一区| 久久成人综合网| 日韩视频在线免费观看| 国产精品免费一区豆花| 久久亚洲精选| 亚洲先锋成人| 欧美成人综合网站| 午夜免费在线观看精品视频| 久久国产一区二区| 日韩一级片网址| 久久综合伊人| 亚洲欧美日韩一区二区三区在线观看| 国产在线播放一区二区三区| 欧美精品999| 久久狠狠婷婷| 亚洲作爱视频| 亚洲激情成人| 久久五月激情| 香蕉久久一区二区不卡无毒影院| 亚洲福利在线看| 国产亚洲一级| 99re66热这里只有精品4| 久久久国际精品| 麻豆精品视频在线| 亚洲视频一二区|