欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

標(biāo)題: 拷貝構(gòu)造函數(shù)和賦值構(gòu)造函數(shù)聲明為私有的作用 [打印本頁(yè)]

作者: 51黑tt    時(shí)間: 2016-3-6 02:07
標(biāo)題: 拷貝構(gòu)造函數(shù)和賦值構(gòu)造函數(shù)聲明為私有的作用
每個(gè)類(lèi)只有一個(gè)賦值函數(shù).

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

  如果我們實(shí)在不想編寫(xiě)拷貝構(gòu)造函數(shù)和賦值函數(shù),又不允許別人使用編譯器生成的缺省函數(shù),怎么辦?

  偷懶的辦法是:只需將拷貝構(gòu)造函數(shù)和賦值函數(shù)聲明為私有函數(shù),不用編寫(xiě)代碼。

  例如:
  class A
  { …
  private:
  A(const A &a); // 私有的拷貝構(gòu)造函數(shù)
  A & operate =(const A &a); // 私有的賦值函數(shù)
  };
  如果有人試圖編寫(xiě)如下程序:
  A b(a); // 調(diào)用了私有的拷貝構(gòu)造函數(shù)
  b = a; // 調(diào)用了私有的賦值函數(shù)
  編譯器將指出錯(cuò)誤,因?yàn)橥饨绮豢梢圆僮鰽的私有函數(shù)。
  3.在編寫(xiě)派生類(lèi)的賦值函數(shù)時(shí),注意不要忘記對(duì)基類(lèi)的數(shù)據(jù)成員重新賦值.






歡迎光臨 (http://m.raoushi.com/bbs/) Powered by Discuz! X3.1