1. gzyueqian
      18529173453

      關(guān)于拷貝構(gòu)造函數(shù)和賦值運(yùn)算符

      更新時(shí)間: 2007-05-08 16:15:35來(lái)源: 粵嵌教育瀏覽量:986


      重點(diǎn):包含動(dòng)態(tài)分配成員的類(lèi) 應(yīng)提供拷貝構(gòu)造函數(shù),并重載"="賦值操作符。


      以下討論中將用到的例子:

      class CExample
      {
      public:
      CExample(){pBuffer=NULL; nSize=0;}
      ~CExample(){delete pBuffer;}
      void Init(int n){ pBuffer=new char[n]; nSize=n;}
      private:
      char *pBuffer; //類(lèi)的對(duì)象中包含指針,指向動(dòng)態(tài)分配的內(nèi)存資源
      int nSize;
      };


      這個(gè)類(lèi)的主要特點(diǎn)是包含指向其他資源的指針。

      pBuffer指向堆中分配的一段內(nèi)存空間。


      一、拷貝構(gòu)造函數(shù)

      int main(int argc, char* argv[])
      {
      CExample theObjone;
      theObjone.Init40);

      //現(xiàn)在需要另一個(gè)對(duì)象,需要將他初始化稱(chēng)對(duì)象一的狀態(tài)
      CExample theObjtwo=theObjone;
      ...
      }


      語(yǔ)句"CExample theObjtwo=theObjone;"用theObjone初始化theObjtwo。

      其完成方式是內(nèi)存拷貝,復(fù)制所有成員的值。

      完成后,theObjtwo.pBuffer==theObjone.pBuffer。

        即它們將指向同樣的地方,指針雖然復(fù)制了,但所指向的空間并沒(méi)有復(fù)制,而是由兩個(gè)對(duì)象共用了。這樣不符合要求,對(duì)象之間不獨(dú)立了,并為空間的刪除帶來(lái)隱患,所以需要采用必要的手段來(lái)避免此類(lèi)情況。

        回顧以下此語(yǔ)句的具體過(guò)程:首先建立對(duì)象theObjtwo,并調(diào)用其構(gòu)造函數(shù),然后成員被拷貝。

        可以在構(gòu)造函數(shù)中添加操作來(lái)解決指針成員的問(wèn)題。

        所以C++語(yǔ)法中除了提供缺省形式的構(gòu)造函數(shù)外,還規(guī)范了另一種特殊的構(gòu)造函數(shù):拷貝構(gòu)造函數(shù),上面的語(yǔ)句中,如果類(lèi)中定義了拷貝構(gòu)造函數(shù),這對(duì)象建立時(shí),調(diào)用的將是拷貝構(gòu)造函數(shù),在拷貝構(gòu)造函數(shù)中,可以根據(jù)傳入的變量,復(fù)制指針?biāo)赶虻馁Y源。

      拷貝構(gòu)造函數(shù)的格式為:構(gòu)造函數(shù)名(對(duì)象的引用)

      提供了拷貝構(gòu)造函數(shù)后的CExample類(lèi)定義為:

      class CExample
      {
      public:
      CExample(){pBuffer=NULL; nSize=0;}
      ~CExample(){delete pBuffer;}
      CExample(const CExample&); //拷貝構(gòu)造函數(shù)
      void Init(int n){ pBuffer=new char[n]; nSize=n;}
      private:
      char *pBuffer; //類(lèi)的對(duì)象中包含指針,指向動(dòng)態(tài)分配的內(nèi)存資源
      int nSize;
      };

      CExample::CExample(const CExample& RightSides) //拷貝構(gòu)造函數(shù)的定義
      {
      nSize=RightSides.nSize; //復(fù)制常規(guī)成員
      pBuffer=new char[nSize]; //復(fù)制指針指向的內(nèi)容
      memcpy(pBuffer,RightSides.pBuffer,nSize*sizeof(char));
      }


        這樣,定義新對(duì)象,并用已有對(duì)象初始化新對(duì)象時(shí),CExample(const CExample& RightSides)將被調(diào)用,而已有對(duì)象用別名RightSides傳給構(gòu)造函數(shù),以用來(lái)作復(fù)制。

      原則上,應(yīng)該為所有包含動(dòng)態(tài)分配成員的類(lèi)都提供拷貝構(gòu)造函數(shù)。

      拷貝構(gòu)造函數(shù)的另一種調(diào)用。

        當(dāng)對(duì)象直接作為參數(shù)傳給函數(shù)時(shí),函數(shù)將建立對(duì)象的臨時(shí)拷貝,這個(gè)拷貝過(guò)程也將調(diào)同拷貝構(gòu)造函數(shù)。

      例如

      BOOL testfunc(CExample obj);

      testfunc(theObjone); //對(duì)象直接作為參數(shù)。

      BOOL testfunc(CExample obj)
      {
      //針對(duì)obj的操作實(shí)際上是針對(duì)復(fù)制后的臨時(shí)拷貝進(jìn)行的
      }


      還有一種情況,也是與臨時(shí)對(duì)象有關(guān)的,當(dāng)函數(shù)中的局部對(duì)象被被返回給函數(shù)調(diào)者時(shí),也將建立此局部對(duì)象的一個(gè)臨時(shí)拷貝,拷貝構(gòu)造函數(shù)也將被調(diào)用

      CTest func()
      {
      CTest theTest;
      return theTest
      }


      二、賦值符的重載

      下面的代碼與上例相似

      int main(int argc, char* argv[])
      {
      CExample theObjone;
      theObjone.Init(40);

      CExample theObjthree;
      theObjthree.Init(60);

      //現(xiàn)在需要一個(gè)對(duì)象賦值操作,被賦值對(duì)象的原內(nèi)容被清除,并用右邊對(duì)象的內(nèi)容填充。
      theObjthree=theObjone;
      return 0;
      }


        也用到了"="號(hào),但與"一、"中的例子并不同,"一、"的例子中,"="在對(duì)象聲明語(yǔ)句中,表示初始化。更多時(shí)候,這種初始化也可用括號(hào)表示。

      例如 CExample theObjone(theObjtwo);

        而本例子中,"="表示賦值操作。將對(duì)象theObjone的內(nèi)容復(fù)制到對(duì)象theObjthree;,這其中涉及到對(duì)象theObjthree原有內(nèi)容的丟棄,新內(nèi)容的復(fù)制。

      但"="的缺省操作只是將成員變量的值相應(yīng)復(fù)制。舊的值被自然丟棄。

        由于對(duì)象內(nèi)包含指針,將造成不良后果:指針的值被丟棄了,但指針指向的內(nèi)容并未釋放。指針的值被復(fù)制了,但指針?biāo)竷?nèi)容并未復(fù)制。

      因此,包含動(dòng)態(tài)分配成員的類(lèi)除提供拷貝構(gòu)造函數(shù)外,還應(yīng)該考慮重載"="賦值操作符號(hào)。

      類(lèi)定義變?yōu)?

      class CExample
      {
      ...
      CExample(const CExample&); //拷貝構(gòu)造函數(shù)
      CExample& operator = (const CExample&); //賦值符重載
      ...
      };


      //賦值操作符重載
      CExample & CExample::operator = (const CExample& RightSides)
      {
      nSize=RightSides.nSize; //復(fù)制常規(guī)成員
      char *temp=new char[nSize]; //復(fù)制指針指向的內(nèi)容
      memcpy(temp,RightSides.pBuffer,nSize*sizeof(char));

      delete []pBuffer; //刪除原指針指向內(nèi)容 (將刪除操作放在后面,避免X=X特殊情況下,內(nèi)容的丟失)
      pBuffer=temp; //建立新指向
      return *this
      }


      三、拷貝構(gòu)造函數(shù)使用賦值運(yùn)算符重載的代碼

      CExample::CExample(const CExample& RightSides)
      {
      pBuffer=NULL;
      *this=RightSides //調(diào)用重載后的"="
      }

      免費(fèi)預(yù)約試聽(tīng)課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 三上悠亚AV福利在线观看 | 亚洲精品第一国产综合亚AV | 亚洲最新网站在线 | 新精品国偷自产在线 | 亚洲Aⅴ男人的天堂在线观看 | 性一区二区视频在线 |