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

隨筆-19  評論-2  文章-0  trackbacks-0

========================
Effective C++   構造、析構、賦值運算
書作者:Scott Meyers
原筆記作者:Justin
========================


Item 5、6   :C++默認編寫的函數
-----------------------------------------
 tag: 默認拷貝函數  copy assignment
 
 如果沒有定義類的構造函數/拷貝函數/拷貝構造函數/析構函數,編譯器會自作主張幫你定義這些函數,而且還是public外加inline的。(估計這是最冷的冷飯了)
 幫寫拷貝函數時僅限于幫你處理一下諸如int的內嵌類型(build-in type)以及自身就有拷貝函數的類對象,再復雜一點的就搞不定了。

 有時候需要禁止某個類對象的拷貝操作,就要避免以上函數的自動生成,需要自己定義這些函數,并且有以下特性
 private
 只是聲明,不給予實現(give no implementation)
 當然要是還是覺得麻煩,干脆直接繼承Boost的noncopyable(自己寫一個類似的也可以),就可以不費吹灰之力的獲得不能拷貝的特性。

Item 7  :為多態基類聲明virtual析構函數
--------------------------------------------
 tag: 多態(polymorphism) 虛函數  virtual function  析構函數

 ·polymorphic base classes 應將析構函數定義為虛函數(virtual function)
 ·當class內至少含一個virtual函數時,才聲明virtual析構函數。
 
 否則在通過基類指針析構一個子類對象的時候,因為沒有虛表(V Table)對析構函數的指引,對象的基類部分是被毀了,對象的子類部分卻沒辦法得到析構(沒有了虛表中的說明它根本不知道有子類的析構函數來析構子類部分!),從而導致內存泄漏。

 virtual函數實現:
  要實現virtual,vptr(virtual table pointer)指針指向一個向函數指針構成的數組,稱為vtbl(virtual table);
  帶有virtual函數的class都有一個對應的vtbl,對象調用virtual函數時,實際被調用的函數取決于該對象的vptr所指的那個vtbl(在其中尋找適當的函數指針)
 
 假設基類指針在析構時要做的事情是奉命救人:指針啊指針,XX地發大水了,你趕緊去把張三一家人(子類對象)救出來。
 指針拿著指令(析構函數)就找到了張三(張三家家長,子類對象的基類部分):張三是吧,你一家人都在這里了吧,跟我走吧。(析構吧,回空余內存里去吧@#¥%)
 如果張三已經沒有其他親戚了,他就是張三家的全部人(這個對象其實就是基類對象)。很簡單,直接跟著指針走就完事了。
 如果張三還有個小弟叫張三瘋(張三家除張三外的一部分,即子類對象的子類部分),張三就必須拿著族譜(V Table)跟指針說哎呀這是我弟啊,把他也析構了吧,張三家對您感恩不盡……也很簡單,一并帶走就完成任務了(完整析構/釋放了整個對象)
 如果,張三沒了族譜,記不得有個張三瘋弟弟,傻乎乎的跟了指針走,大家也以為張三一家都被救出來了。災區里就只剩下張三瘋一個人在瘋跑了(memory leak)

 另一方面,如果不準備把某個類用作多態中的基類,就沒必要定義析構函數為虛函數。這樣除了增加代碼大小開銷外(因為需要空間存放虛表),沒有任何好處。(這個倒是很多書上沒說過的)

 如果張三家本來就只有張三一個人,他就沒必要還要帶著個空白的族譜了。逃命的時候能扔就扔嘛。


 最后提到的一點和抽象類有關。抽象類是有純虛函數的類,只能作為接口,不能有自己的對象。在設計軟件框架的時候會有需要用到抽象類的時候。可是如果有這么一個類,需要設計為抽象類,但是卻找不到一個成員函數可以拉去做純虛函數,那么這個時候就把析構函數定義為純虛函數好了。只是同時還要給它一個空的實現。

 class::~class() {}


 

Item 8 :別讓異常逃離析構函數
-------------------------------------------
 tag:異常 try catch  析構函數
 
 ·在析構函數中不能拋出異常。 若被析構函數調用的函數可能會拋出異常,析構函數應該捕捉任何異常,并吞下(不傳播)或結束程序。
 ·若一個操作可能出現異常,客戶需要對這個異常作出反應。class應提供一個普通函數來執行該函數,而不是在析構函數內調用。

 異常不像函數調用,一旦拋出(throw),就回不來了。
 如果在析構函數中拋出了異常,有一部分釋放/摧毀對象成員的操作可能就無法進行。因為某個異常,導致了所在的析構函數無法完成全部析構任務。

 可是要是真的需要對析構動作中出現的錯誤/異常進行處理咋辦?書中自有解決方案:從差的到好的。

 在析構函數內布置catch,一旦發生異常就會被捕獲,然后簡單調用std::abort自殺
  點評:干脆是干脆了,但是這樣猝死會不會有點太突然?
 也是在函數內布置catch,但是遇到異常就把它直接吃到肚子里(大師語:Swallow the exception)。
  點評:一般不該這樣處理,畢竟發生了不好的事。但如果真的想要程序繼續帶傷上陣,也確定這樣不會有問題,那也不會有人有意見。
  
 除了在函數里布置catch,并采用以上任一方法,另外實現一個可供用戶調用的函數接口,用來處理這些有可能出錯的析構工作。
  點評:大師給予這個方案高度的評價,因為這樣不但有以上兩種方法的效果,還給用戶一個參與處理異常的機會(調用接口函數)。如果用戶沒有(或者忘記)用該函數處理析構的動作,那么析構函數也會自覺挑起這個任務。而這個時候如果還出問題,用戶也沒有什么理由來責怪了:是你自己不想要管的!



Item 9 :不在構造和析構過程中調用 virtual 函數
-----------------------------------------------------
 tag:
 
 擁有虛函數的類就有虛表,虛表可能會引發子類相應虛函數的調用,在這些調用中有可能對某些子類對象成員的訪問。
 在構造一個子類對象時:   開始構造父類部分 -> 完成父類部分并開始構造子類部分 -> 完成子類部分    (完成整個構造工作)
 析構一個子類對象的時:  開始析構子類部分 -> 子類析構完畢并開始析構父類部分 -> 完成析構父類部分(完成整個析構工作)

 在構造函數的第一步,子類對象成員還不存在,調用虛函數有可能會訪問不存在的子類成員;
 哪怕到了第二步,因為子類對象還沒有完全構造完畢,此時調用虛函數也是危險的。事實上在整個構造過程中,該對象都被視作一個父類對象。
 反過來也是同樣道理,在析構函數的第一步,子類成員已經開始銷毀,不能調用虛函數;到了第二步,整個子類部分都沒有了,更不能用虛函數了。
 而在整個析構過程中,該對象也是被看作是父類對象的。
 
 確保虛函數不會在對象構造/析構過程中被調用:

 方法之一就是用參數傳遞代替虛函數機制。
 把可能被構造函數調用的虛函數改成非虛函數,然后讓父類的構造函數將需要的信息/數據通過參數傳遞給子類構造函數。
  Class Parent
  {
   public :
      Parent();
      Parent( const  std:: string &  WordsFromChild){
          DoStuff(WordsFromChild);
          // ..
      };
      void  DoStuff( const  std:: string &  WordsFromChild);
  }   
    Class Child :  public  Parent
    {
  public :
      Child( /**/ /* some parameters here */ ) : Parent(TellParent( /**/ /* some parameters here */ )) {
         // ..
      };
  private :
      static  std:: string &  TellParent( /**/ /* some parameters here */ );
    }
     也許看到這里會想:要是TellParent()中訪問了未被初始化的子類成員呢?那不也是一樣有問題么?
     注意,這就是為什么前面有個static限定的原因。因為靜態函數可以在對象的初始化階段就開始工作,更詳細的描述看這里。
 子類的虛表在子類的構造函數時生成,所以在父類的構造函數中調用虛函數使用的是父類的版本。
 子類和父類對象都會有自己的虛表,里面安置的是自己版本的虛函數實現。



Item 10-12 :  拷貝運算符
--------------------------
 tag:assignment operator(賦值運算符)  自我賦值  copying函數
 
 ·令賦值(assignment)操作符返回一個reference to *this。 可實現(a=b=c)。
 ·處理自我賦值
 ·構造函數用來初始化新對象,而 assignment操作符只施行于已初始化對象身上。
 ·copying函數應該確保復制“對象內所有成員變量”和“所有 base class成分”
 
 1、
  在函數入口檢查是否屬于自拷貝(例如:檢查指針是否指向同一片內存),如果是,啥也不干直接返回。否則屬于正常情況的拷貝。
  這樣解決了self-assignment-unsafe的問題,但是沒能避免exception-unsafe。
  
 2、
  第二種方法比較簡單,只是整理一下指令的順序。但是卻同時解決了自賦值和拋出異常帶來的問題。繼續無恥的抄寫代碼一段: 

   Widget&  Widget::operator=(const Widget& rhs)
   {
      Bitmap *pOrig = pb;            // remember original pb
      pb = new Bitmap(*rhs.pb);      // make pb point to a copy of *pb
      delete pOrig;                  // delete the original pb
      return *this;
   }

  這樣的做法在解決以上兩個問題的同時卻也降低了執行的效率:不論什么情況,這個賦值函數都要創建一個新的Bitmap對象。
  第一種方法的額外支出:判斷語句必然地引入了程序的分支(branch),于是指令的預取(prefetch)、緩沖(caching)、流水線處理(pipelining)的效率就會被降低。
 3、
  Copy And Swap。改賦值為交換。

   void swap(Widget& rhs);   //交換*this 和rhs的數據;

   Widget&  Widget::operator=(const Widget& ths)
   {
    Widget temp(ths);  //為rhs數據制作一份副本
    swap(temp);    //將*this數據和上述副本的數據交換。
    return *this;
   }
   
   Widget&  Widget::operator=(Widget rhs)    // rhs is a copy of the object
   {                                        // passed in — note pass by val
      swap(rhs);                             // swap *this's data with the copy's
      return *this;
   }利用參數傳值,隱性的構造了一個Widget對象。然后將新對象和本對象中的數據成員交換,達到為本對象賦值的效果。
  新的臨時對象在跳出函數后自動銷毀。剛才說的兩個unsafe,都不會存在。
  這樣開銷較大了,無論什么時候都要構造新的對象。用swap來完成賦值的做法有點邏輯混淆。但這樣做很有可能讓編譯器生成更有效率的代碼。

 ---------------------------
  如何保證在賦值/拷貝的時候能夠將所有的成員完整拷貝過去?
 對于簡單的數據成員,編譯器自動生成的拷貝函數可以保證一個不漏都幫你拷貝;
 如果是比較復雜的成員(比如說指向一片內存空間的指針),編譯器就沒有足夠的智商把這些成員拷貝到另外一個對象中去了。

 在增加類成員以后記得更新拷貝函數,以免拷貝不完全。
 子類的拷貝函數把自己的成員都拷貝了,但是卻漏了把父類對象的成員拷貝到新的對象中。 在子類的拷貝函數中調用父類的拷貝函數

   Widget&  Widget:: operator   =  (Widget src) 
  {
     swap(src);                                // copy-and-swap
     WidgetParent:: operator   =  (src);       // invoking the parent's copy assignment operator
     return   * this ;
  }

  最后的最后,通常來說在拷貝函數和拷貝構造函數中的實現大多相同,
 不要在拷貝函數中調用拷貝構造函數或者反之。如果真的需要避免代碼的重復,大可定義一個私有的函數來負責前面兩者相同的部分。

posted on 2010-03-15 22:44 Euan 閱讀(574) 評論(0)  編輯 收藏 引用 所屬分類: C/C++
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            久久经典综合| 欧美一区二区精品在线| 亚洲国产精品成人精品| 久久人人爽人人| 亚洲精品国产精品国自产观看| 亚洲国产免费看| 欧美日韩国产在线一区| 欧美在线91| 久久久久久亚洲精品杨幂换脸| 亚洲成人在线视频网站| 亚洲精品视频在线播放| 国产情人综合久久777777| 葵司免费一区二区三区四区五区| 美女脱光内衣内裤视频久久网站| 一本色道88久久加勒比精品| 亚洲一区二区精品视频| 黄色综合网站| 亚洲美女区一区| 国内精品伊人久久久久av一坑| 亚洲电影免费观看高清完整版在线| 欧美日韩成人在线| 久久久亚洲国产美女国产盗摄| 欧美经典一区二区| 欧美在线视频a| 欧美激情一区在线| 久久久噜噜噜久久久| 欧美日韩不卡合集视频| 久久精品国产综合精品| 亚洲在线电影| 久久精品成人一区二区三区| 免费日韩av片| 欧美在线视频网站| 欧美精品麻豆| 老司机成人在线视频| 国产精品www| 亚洲片区在线| 亚洲大片av| 久久黄金**| 欧美一区网站| 欧美午夜一区二区福利视频| 亚洲第一主播视频| 一区二区在线看| 午夜精品一区二区三区在线| 亚洲视频免费| 欧美激情aⅴ一区二区三区| 久久久久免费视频| 国产精品成人一区二区| 亚洲精品乱码久久久久| 91久久国产自产拍夜夜嗨| 欧美中文字幕久久| 久久国产精品黑丝| 国产久一道中文一区| 一区二区三区视频在线播放| 日韩视频在线免费观看| 免费看精品久久片| 欧美电影在线播放| 亚洲激情电影中文字幕| 久久综合色影院| 亚洲国产成人不卡| 亚洲精品三级| 欧美日韩国产美| 亚洲美女av网站| 国产精品99久久久久久有的能看| 欧美黄免费看| 亚洲精品影院| 香蕉免费一区二区三区在线观看 | 亚洲一级一区| 亚欧成人精品| 国产网站欧美日韩免费精品在线观看| 亚洲欧美卡通另类91av| 久久超碰97人人做人人爱| 国产欧美一区二区视频| 久久久91精品国产| 欧美国产一区在线| 99视频超级精品| 国产精品视区| 久久精品一区二区| 最新国产の精品合集bt伙计| 中文亚洲免费| 国产欧美精品| 美女脱光内衣内裤视频久久影院| 亚洲欧洲精品一区二区精品久久久| 亚洲精品之草原avav久久| 欧美日韩一二三四五区| 亚洲欧美综合国产精品一区| 鲁鲁狠狠狠7777一区二区| 亚洲美女淫视频| 国产精品中文字幕欧美| 久色成人在线| 夜久久久久久| 久久午夜色播影院免费高清| 99国产精品自拍| 国产在线精品一区二区夜色| 欧美福利视频网站| 欧美理论电影网| 欧美激情第一页xxx| 宅男噜噜噜66国产日韩在线观看| 国产欧美日韩在线视频| 欧美 亚欧 日韩视频在线| 亚洲视频axxx| 欧美国产先锋| 久久久噜噜噜久噜久久| 亚洲天堂av图片| 在线成人h网| 国产精品乱人伦一区二区| 久久亚洲欧美| 亚洲欧美日韩爽爽影院| 亚洲激情成人网| 久久久久九九视频| 亚洲免费网站| 日韩一级大片| 亚洲成色www久久网站| 国产精品久久久久aaaa| 毛片一区二区三区| 午夜亚洲视频| 亚洲综合电影| 一本色道久久99精品综合| 欧美高清日韩| 久久久视频精品| 欧美在线三级| 欧美一区二区在线播放| 在线中文字幕一区| 洋洋av久久久久久久一区| 亚洲国产导航| 狠狠综合久久av一区二区小说| 国产精品蜜臀在线观看| 欧美日韩精品一区二区三区| 免费看的黄色欧美网站| 久久综合九色九九| 久久精品国产免费观看| 欧美一区二区国产| 午夜精品一区二区三区四区| 亚洲一二三级电影| 亚洲一区二区三区久久| 夜色激情一区二区| 亚洲美女色禁图| av成人国产| 亚洲影院在线| 亚洲男同1069视频| 亚洲女ⅴideoshd黑人| 翔田千里一区二区| 欧美一区二区在线视频| 午夜国产欧美理论在线播放| 亚洲欧美一区二区三区极速播放| 亚洲自拍偷拍福利| 亚洲欧美在线高清| 久久精品国产v日韩v亚洲 | 最新日韩在线视频| 亚洲国产综合在线| 亚洲精品小视频| 宅男噜噜噜66一区二区66| 亚洲一区二区av电影| 亚洲免费一在线| 久久激情综合网| 欧美77777| 欧美三级中文字幕在线观看| 欧美日韩另类一区| 国产深夜精品| 亚洲电影第1页| 一本色道久久综合| 亚洲一区三区电影在线观看| 亚洲欧美久久久| 久久一区二区三区超碰国产精品| 欧美a级在线| 日韩视频在线播放| 亚洲欧美国产高清| 老司机精品视频网站| 欧美色123| 激情一区二区| 亚洲视频在线观看免费| 欧美一区二区三区久久精品| 蜜乳av另类精品一区二区| 国产精品日本精品| 一本一本大道香蕉久在线精品| 亚洲精品一区二区三区99| 亚洲制服av| 欧美搞黄网站| 中日韩视频在线观看| 久久久久久久久久久一区| 欧美精品一区在线发布| 国产欧美一区视频| 99视频日韩| 免费永久网站黄欧美| 亚洲愉拍自拍另类高清精品| 鲁大师影院一区二区三区| 国产精品毛片高清在线完整版| 亚洲二区视频| 小嫩嫩精品导航| 亚洲黄一区二区| 欧美在线亚洲在线| 国产精品国产亚洲精品看不卡15| 影音先锋久久| 欧美在线日韩| 亚洲视频播放| 欧美日韩视频免费播放| 亚洲国产精品ⅴa在线观看 | 韩国成人理伦片免费播放| 亚洲一区三区视频在线观看| 亚洲国产99精品国自产| 久久九九热re6这里有精品|