日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

拷貝構(gòu)造函數(shù)和賦值構(gòu)造函數(shù)的異同

 306 2009-05-02

拷貝構(gòu)造函數(shù)和賦值構(gòu)造函數(shù)的異同 2008-08-19 10:13

由于并非所有的對象都會使用拷貝構(gòu)造函數(shù)和賦值函數(shù),程序員可能對這兩個(gè)函數(shù)
  有些輕視。請先記住以下的警告,在閱讀正文時(shí)就會多心:
   如果不主動編寫拷貝構(gòu)造函數(shù)和賦值函數(shù),編譯器將以“位拷貝”
  的方式自動生成缺省的函數(shù)。倘若類中含有指針變量,那么這兩個(gè)缺省的函數(shù)就隱
  含了錯(cuò)誤。以類String 的兩個(gè)對象a,b 為例,假設(shè)a.m_data 的內(nèi)容為“hello”,
  b.m_data 的內(nèi)容為“world”。
  現(xiàn)將a 賦給b,缺省賦值函數(shù)的“位拷貝”意味著執(zhí)行b.m_data = a.m_data。
  這將造成三個(gè)錯(cuò)誤:一是b.m_data 原有的內(nèi)存沒被釋放,造成內(nèi)存泄露;二是
  b.m_data 和a.m_data 指向同一塊內(nèi)存,a 或b 任何一方變動都會影響另一方;三
  是在對象被析構(gòu)時(shí),m_data 被釋放了兩次。
   拷貝構(gòu)造函數(shù)和賦值函數(shù)非常容易混淆,常導(dǎo)致錯(cuò)寫、錯(cuò)用。拷貝構(gòu)造函數(shù)是在對
  象被創(chuàng)建時(shí)調(diào)用的,而賦值函數(shù)只能被已經(jīng)存在了的對象調(diào)用。以下程序中,第三
  個(gè)語句和第四個(gè)語句很相似,你分得清楚哪個(gè)調(diào)用了拷貝構(gòu)造函數(shù),哪個(gè)調(diào)用了賦
  值函數(shù)嗎?
  String a(“hello”);
  String b(“world”);
  String c = a; // 調(diào)用了拷貝構(gòu)造函數(shù),最好寫成 c(a);
  c = b; // 調(diào)用了賦值函數(shù)
  本例中第三個(gè)語句的風(fēng)格較差,宜改寫成String c(a) 以區(qū)別于第四個(gè)語句。
  類String 的拷貝構(gòu)造函數(shù)與賦值函數(shù)
  // 拷貝構(gòu)造函數(shù)
  String::String(const String &other)
  {
  // 允許操作other 的私有成員m_data
  int length = strlen(other.m_data);
  m_data = new char[length+1];
  strcpy(m_data, other.m_data);
  }
  // 賦值函數(shù)
  String & String::operate =(const String &other)
  {
  // (1) 檢查自賦值
  if(this == &other)
  return *this;
  // (2) 釋放原有的內(nèi)存資源
  delete [] m_data;
  // (3)分配新的內(nèi)存資源,并復(fù)制內(nèi)容
  int length = strlen(other.m_data);
  m_data = new char[length+1];
  strcpy(m_data, other.m_data);
  // (4)返回本對象的引用
  return *this;
  }
  類String 拷貝構(gòu)造函數(shù)與普通構(gòu)造函數(shù)的區(qū)別是:在函數(shù)入口處無
  需與NULL 進(jìn)行比較,這是因?yàn)?#8220;引用”不可能是NULL,而“指針”可以為NULL。
  類String 的賦值函數(shù)比構(gòu)造函數(shù)復(fù)雜得多,分四步實(shí)現(xiàn):
  (1)第一步,檢查自賦值。你可能會認(rèn)為多此一舉,難道有人會愚蠢到寫出 a = a 這
  樣的自賦值語句!的確不會。但是間接的自賦值仍有可能出現(xiàn),例如
  // 內(nèi)容自賦值
  b = a;
  …
  c = b;
  …
  a = c;
  // 地址自賦值
  b = &a;
  …
  a = *b;
  也許有人會說:“即使出現(xiàn)自賦值,我也可以不理睬,大不了化點(diǎn)時(shí)間讓對象復(fù)制
  自己而已,反正不會出錯(cuò)!”
  他真的說錯(cuò)了。看看第二步的delete,自殺后還能復(fù)制自己嗎?所以,如果發(fā)現(xiàn)自
  賦值,應(yīng)該馬上終止函數(shù)。注意不要將檢查自賦值的if 語句
  if(this == &other)
  錯(cuò)寫成為
  if( *this == other)
 ?。?)第二步,用delete 釋放原有的內(nèi)存資源。如果現(xiàn)在不釋放,以后就沒機(jī)會了,將
  造成內(nèi)存泄露。
 ?。?)第三步,分配新的內(nèi)存資源,并復(fù)制字符串。注意函數(shù)strlen 返回的是有效字符
  串長度,不包含結(jié)束符‘\0’。函數(shù)strcpy 則連‘\0’一起復(fù)制。
  (4)第四步,返回本對象的引用,目的是為了實(shí)現(xiàn)象 a = b = c 這樣的鏈?zhǔn)奖磉_(dá)。注
  意不要將 return *this 錯(cuò)寫成 return this 。那么能否寫成return other 呢?效果
  不是一樣嗎?
  不可以!因?yàn)槲覀儾恢绤?shù)other 的生命期。有可能other 是個(gè)臨時(shí)對象,在賦
  值結(jié)束后它馬上消失,那么return other 返回的將是垃圾。
  偷懶的辦法處理拷貝構(gòu)造函數(shù)與賦值函數(shù)
  如果我們實(shí)在不想編寫拷貝構(gòu)造函數(shù)和賦值函數(shù),又不允許別人使用編譯器生成的
  缺省函數(shù),怎么辦?
  偷懶的辦法是:只需將拷貝構(gòu)造函數(shù)和賦值函數(shù)聲明為私有函數(shù),不用編寫代碼。
  例如:
  class A
  { …
  private:
  A(const A &a); // 私有的拷貝構(gòu)造函數(shù)
  A & operate =(const A &a); // 私有的賦值函數(shù)
  };
  如果有人試圖編寫如下程序:
  A b(a); // 調(diào)用了私有的拷貝構(gòu)造函數(shù)
  b = a; // 調(diào)用了私有的賦值函數(shù)
  編譯器將指出錯(cuò)誤,因?yàn)橥饨绮豢梢圆僮鰽 的私有函數(shù)。

 

一、
拷貝構(gòu)造,是一個(gè)的對象來初始化一邊內(nèi)存區(qū)域,這邊內(nèi)存區(qū)域就是你的新對象的內(nèi)存區(qū)域賦值運(yùn)算,對于一個(gè)已經(jīng)被初始化的對象來進(jìn)行operator=操作
class   A;     
 A  a;  
 A  b=a;   //拷貝構(gòu)造函數(shù)調(diào)用  
 //或  
 A  b(a);   //拷貝構(gòu)造函數(shù)調(diào)用  
 ///////////////////////////////////     
 A  a;  
 A  b;  
 b =a;   //賦值運(yùn)算符調(diào)用   

你只需要記住,在C++語言里,  
 String   s2(s1);  
 String   s3   =   s1;  
 只是語法形式的不同,意義是一樣的,都是定義加初始化,都調(diào)用拷貝構(gòu)造函數(shù)。

二、
一般來說是在數(shù)據(jù)成員包含指針對象的時(shí)候,應(yīng)付兩種不同的處理需求的 一種是復(fù)制指針對象,一種是引用指針對象 copy大多數(shù)情況下是復(fù)制,=則是引用對象的     
例子:  
  class   A  
  {  
          int   nLen;  
          char   *   pData;  
  }  
  顯然  
  A   a,   b;  
  a=b的時(shí)候,對于pData數(shù)據(jù)存在兩種需求  
  第一種copy 
      a.pData   =   new   char   [nLen];  
      memcpy(a.pData,   b.pData,   nLen);  
  另外一種(引用方式):  
      a.pData   =   b.pData  
   
  通過對比就可以看到,他們是不同的  
  往往把第一種用copy使用,第二種用=實(shí)現(xiàn)
  你只要記住拷貝構(gòu)造函數(shù)是用于類中指針,對象間的COPY  

三、
  和拷貝構(gòu)造函數(shù)的實(shí)現(xiàn)不一樣    
  拷貝構(gòu)造函數(shù)首先是一個(gè)構(gòu)造函數(shù),它調(diào)用的時(shí)候產(chǎn)生一個(gè)對象,是通過參數(shù)傳進(jìn)來的那個(gè)對象來初始化,產(chǎn)生的對象。  
  operator=();是把一個(gè)對象賦值給一個(gè)原有的對象,所以如果原來的對象中有內(nèi)存分配要先把內(nèi)存釋放掉,而且還要檢查一下兩個(gè)對象是不是同一個(gè)對象,如果是的話就不做任何操作。


還要注意的是拷貝構(gòu)造函數(shù)是構(gòu)造函數(shù),不返回值  

  而賦值函數(shù)需要返回一個(gè)對象自身的引用,以便賦值之后的操作  

  你肯定知道這個(gè):  

    int   a,   b;  

    b   =   7;  

    Func(   a   =   b   );   //   把i賦值后傳給函數(shù)Func(   int   )  

  同理:  

   CMyClass   obj1,   obj2;  

      obj1.Initialize();      

      Func2(   obj1   =   obj2   );   //如果沒有返回引用,是不能把值傳給Func2的  

   

      注:  

   CMyClass   &   CMyClass::   operator   =   (   CMyClass   &   other   )  

      {  

              if(   this   ==   &other   )  

                      return   *this;  

              //   賦值操作...  

              return   *this  

      }  

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多