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

隨筆-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>
            亚洲精品综合久久中文字幕| 亚洲韩国青草视频| 久久全球大尺度高清视频| 亚洲欧美另类国产| 亚洲一区二区三区乱码aⅴ| 亚洲一区欧美激情| 久久疯狂做爰流白浆xx| 免费成人黄色| 日韩一级在线| 欧美一级久久| 久久综合影视| 欧美日韩综合不卡| 国产日韩欧美综合精品| 最近看过的日韩成人| 亚洲午夜视频在线| 久久视频精品在线| 亚洲国产精品日韩| 亚洲美女中文字幕| 久久av一区二区| 欧美日韩裸体免费视频| 国产伦精品一区二区三区四区免费| 国模吧视频一区| 亚洲欧洲另类国产综合| 亚洲欧美日韩爽爽影院| 欧美gay视频| 亚洲伊人网站| 久久国产精品久久国产精品| 欧美国产日韩xxxxx| 国产精品久久久亚洲一区| 激情综合网址| 亚洲女人天堂av| 亚洲第一精品影视| 欧美一区午夜精品| 国产精品草莓在线免费观看| 在线日韩欧美| 欧美在线看片| 99视频精品全部免费在线| 噜噜噜噜噜久久久久久91| 国产日韩一区二区三区在线播放| 99精品国产热久久91蜜凸| 久久久另类综合| 亚洲私拍自拍| 欧美日韩国产在线| 亚洲人成在线免费观看| 奶水喷射视频一区| 欧美一区二区在线播放| 国产麻豆精品视频| 午夜在线一区| 亚洲视频欧美在线| 国产精品jizz在线观看美国 | 欧美ed2k| 性做久久久久久| 欧美午夜一区二区福利视频| 亚洲人精品午夜| 欧美高清视频一二三区| 欧美在线观看视频| 国产欧美另类| 欧美在线一二三| 亚洲一区二区少妇| 国产精品男女猛烈高潮激情| 一区二区三区视频在线观看 | 亚洲国产精品久久91精品| 久久久欧美精品sm网站| 国产欧美日韩激情| 亚洲一区中文| 亚洲欧美日韩国产一区| 国产精品日韩久久久| 亚洲欧美日韩一区二区三区在线| 一本大道久久a久久综合婷婷| 欧美日韩视频| 午夜精品在线看| 亚洲欧美日韩精品久久久久| 国产精品日本一区二区| 欧美一区二区三区视频在线 | 亚洲伊人伊色伊影伊综合网| 在线天堂一区av电影| 欧美成人国产一区二区| 久久久久久国产精品mv| 激情欧美一区二区三区在线观看| 久久久欧美精品| 久久国产视频网| 91久久在线视频| 一区二区三区国产| 国产精品影音先锋| 久久精品国产精品| 久热精品视频在线免费观看| 亚洲第一主播视频| 亚洲另类黄色| 国产亚洲一区二区在线观看| 欧美成人第一页| 欧美女激情福利| 欧美一区二区精品久久911| 久久精品导航| 一本久道久久久| 欧美制服丝袜| 在线午夜精品自拍| 欧美制服丝袜第一页| 亚洲日韩欧美视频一区| 亚洲午夜日本在线观看| 一区二区三区亚洲| 亚洲日本一区二区| 国产精品一区二区久激情瑜伽| 欧美激情视频网站| 国产精品欧美久久| 欧美成人69av| 国产视频一区在线观看一区免费| 欧美大成色www永久网站婷| 国产精品成av人在线视午夜片| 美女脱光内衣内裤视频久久影院| 国产精品video| 欧美国产日本在线| 国产亚洲亚洲| 亚洲视频观看| 日韩视频在线观看| 久久亚洲精品一区二区| 欧美一区二区三区免费视| 欧美日本韩国在线| 欧美成人精品| 国产一区再线| 欧美一区二区三区久久精品| 亚洲影院免费| 欧美日韩视频不卡| 亚洲欧洲偷拍精品| 最近中文字幕日韩精品| 久久亚洲精品一区| 久久综合九九| 国产亚洲美州欧州综合国| 亚洲一区三区电影在线观看| 洋洋av久久久久久久一区| 男人的天堂成人在线| 蜜桃av一区| 一区二区在线视频观看| 新67194成人永久网站| 欧美一区二区视频网站| 国产精品美女久久久久久免费| 国产精品99久久久久久久女警 | 欧美www视频在线观看| 欧美一二区视频| 国产精品护士白丝一区av| 亚洲乱码国产乱码精品精98午夜 | 久久国产精品亚洲va麻豆| 国产精品伦一区| 亚洲一二三级电影| 亚洲欧美日韩国产综合精品二区| 欧美三级乱码| 亚洲一区免费观看| 久久久精品动漫| 黄色一区二区在线| 麻豆久久婷婷| 亚洲黄一区二区三区| 亚洲图片欧美日产| 国产精品色婷婷| 久久精品视频va| 嫩模写真一区二区三区三州| 亚洲激情婷婷| 国产精品国产三级国产普通话99| 午夜精品999| 蜜臀久久99精品久久久画质超高清 | 免费亚洲一区二区| 亚洲人妖在线| 欧美日韩系列| 亚洲自拍偷拍福利| 免费在线看一区| 亚洲免费观看在线观看| 国产精品永久在线| 久久久久久网站| 亚洲精品综合在线| 久久九九电影| 亚洲伦理自拍| 国产精品久久一级| 久久综合国产精品台湾中文娱乐网| 亚洲第一网站| 亚洲欧美日韩另类| 亚洲国产欧美一区二区三区丁香婷| 欧美日本韩国| 久久九九久久九九| 一本大道久久a久久精二百| 久久一日本道色综合久久| 一本久久综合| 激情综合中文娱乐网| 国产精品成人午夜| 欧美成年网站| 久久久国产一区二区三区| 一区二区三区精品国产| 麻豆精品一区二区av白丝在线| 国产精品99久久久久久宅男 | 欧美精品123区| 亚洲欧美国产精品桃花| 亚洲福利视频专区| 久久成年人视频| 亚洲天天影视| 99pao成人国产永久免费视频| 国产亚洲精品久久久久动| 欧美性一二三区| 欧美电影打屁股sp| 久久久精品国产99久久精品芒果| 亚洲性人人天天夜夜摸| 91久久久久久久久久久久久| 欧美xxx成人| 久久最新视频|