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

隨筆-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>
            蜜桃av一区二区| 亚洲二区视频| 国产一区二区精品久久91| 欧美日韩免费高清| 欧美日韩亚洲一区二区三区四区| 免费成人激情视频| 久久精品国产一区二区三区免费看| 午夜电影亚洲| 欧美中文字幕视频| 久久精品二区三区| 久久综合国产精品| 久久性天堂网| 最新国产成人av网站网址麻豆| 亚洲精品中文字幕在线| 日韩午夜在线视频| 午夜精品久久久久影视| 久久久久久久久久久久久女国产乱 | 亚洲国产成人高清精品| 亚洲观看高清完整版在线观看| 亚洲高清不卡一区| 亚洲午夜电影网| 久久不射中文字幕| 欧美激情一区二区三区四区| 午夜精品成人在线视频| 欧美成人dvd在线视频| 国产精品久久国产愉拍 | 亚洲无毛电影| 久久亚洲国产精品日日av夜夜| 91久久线看在观草草青青| 日韩香蕉视频| 久久综合久久综合久久综合| 欧美日韩国产经典色站一区二区三区 | 亚洲网站啪啪| 暖暖成人免费视频| 国产亚洲一区二区在线观看| 亚洲激情自拍| 久久久无码精品亚洲日韩按摩| 亚洲人成在线影院| 久久久久久久久久久久久女国产乱 | 韩国成人福利片在线播放| 亚洲人成人99网站| 久久免费的精品国产v∧| 亚洲激情影视| 免费一级欧美在线大片| 国产亚洲一区在线| 亚洲午夜一区二区三区| 亚洲激情av| 久久免费一区| 国产在线播放一区二区三区| 亚洲欧美伊人| 99国产精品视频免费观看一公开 | 正在播放欧美视频| 免费精品99久久国产综合精品| 中文亚洲视频在线| 欧美激情一区二区三级高清视频 | 亚洲欧美在线看| 欧美日韩中文| 国产精品99久久不卡二区| 欧美激情aaaa| 蜜臀av国产精品久久久久| 黄网动漫久久久| 久久婷婷av| 久久青青草原一区二区| 亚洲美女视频在线免费观看| 最新国产の精品合集bt伙计| 久久国产日韩| 久久久不卡网国产精品一区| 欧美日韩精品伦理作品在线免费观看 | 国产精品国产三级国产aⅴ浪潮| 亚洲精品一区二区三区蜜桃久 | 久久综合色影院| 久久久夜色精品亚洲| 激情综合久久| 女人色偷偷aa久久天堂| 久久亚洲私人国产精品va媚药| 国内精品伊人久久久久av一坑| 久久人人九九| 美女尤物久久精品| 一区二区三区偷拍| 国产精品99久久久久久久vr| 国产精品国产三级国产普通话99| 亚洲女人小视频在线观看| 午夜精品免费在线| 激情av一区| 亚洲欧洲精品一区二区三区波多野1战4| 美女任你摸久久| 欧美高清视频| 一本久道久久综合狠狠爱| 一区二区冒白浆视频| 国产综合视频| 99riav1国产精品视频| 国产精品午夜久久| 噜噜噜久久亚洲精品国产品小说| 免费看成人av| 性欧美办公室18xxxxhd| 久久在线视频| 亚洲主播在线播放| 久久国产精品久久国产精品| 在线免费不卡视频| 一本一本久久a久久精品综合麻豆| 国产精品一卡二| 亚洲国产第一页| 国产精品国产| 亚洲国产日韩欧美在线99 | 亚洲深夜福利| 亚洲国产福利在线| 一区二区三区www| 狠狠爱成人网| 亚洲午夜一区二区三区| 在线成人性视频| 亚洲午夜电影网| 亚洲每日更新| 欧美一区激情视频在线观看| 一区二区三区四区精品| 久久国产精品久久久久久久久久 | 欧美性开放视频| 欧美成人午夜激情| 国产精品一区二区三区成人| 亚洲精品美女久久久久| 在线观看免费视频综合| 亚洲视频精品| 日韩一区二区精品葵司在线| 久久精品免费| 欧美在线免费看| 欧美日韩视频一区二区| 欧美成人第一页| 国产一区二区电影在线观看 | 亚洲午夜视频在线观看| 免费看av成人| 欧美国产乱视频| 激情成人av| 性8sex亚洲区入口| 欧美一区二区三区在线播放| 欧美视频中文在线看| 亚洲精选成人| 一区二区三区四区五区精品视频| 欧美肥婆在线| 亚洲精品一二区| 亚洲卡通欧美制服中文| 久久天天躁狠狠躁夜夜av| 久久综合99re88久久爱| 国产网站欧美日韩免费精品在线观看 | 久久嫩草精品久久久精品一| 国产精品一卡二| 午夜久久资源| 久久久女女女女999久久| 国语自产精品视频在线看| 欧美中文在线视频| 欧美+亚洲+精品+三区| 亚洲激情偷拍| 欧美精品久久久久久| 亚洲精品国久久99热| 久久都是精品| 欧美日韩中文在线| 亚洲每日在线| 一区二区三区四区在线| 国产精品日韩精品| 亚洲乱码国产乱码精品精天堂| 亚洲国产精品一区| 欧美精品一区二区高清在线观看| 亚洲精品美女久久久久| 国产精品99久久久久久宅男| 欧美午夜一区二区福利视频| 亚洲一区二区三区四区五区黄| 性高湖久久久久久久久| 国产精品免费电影| 久久久999国产| 最新国产成人在线观看| 性色一区二区三区| 激情综合网激情| 欧美精品日韩www.p站| 亚洲一品av免费观看| 麻豆91精品| 亚洲在线观看视频网站| 国内自拍一区| 欧美日韩直播| 美玉足脚交一区二区三区图片| 宅男精品导航| 亚洲高清在线| 久久嫩草精品久久久精品一| 日韩视频在线观看| 国产亚洲精品久久久| 欧美激情欧美狂野欧美精品| 亚洲欧美日韩成人高清在线一区| 欧美高清在线一区二区| 亚洲视频电影图片偷拍一区| 精品69视频一区二区三区 | 欧美国产在线观看| 欧美一级专区免费大片| 在线视频你懂得一区| 亚洲成色最大综合在线| 国产精品一区2区| 久热re这里精品视频在线6| 亚洲一区二区成人| 欧美激情精品久久久久久久变态| 蜜臀99久久精品久久久久久软件| 欧美黄色片免费观看| 亚洲无亚洲人成网站77777| 一区在线视频观看| 国产精品久久久久久久久久直播|