• <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>

            woaidongmao

            文章均收錄自他人博客,但不喜標(biāo)題前加-[轉(zhuǎn)貼],因其丑陋,見諒!~
            隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
            數(shù)據(jù)加載中……

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

              拷貝構(gòu)造函數(shù),是一種特殊的構(gòu)造函數(shù),它由編譯器調(diào)用來完成一些基于同一類的其他對象的構(gòu)建及初始化。其唯一的參數(shù)(對象的引用)是不可變的(const類型)。此函數(shù)經(jīng)常用在函數(shù)調(diào)用時用戶定義類型的值傳遞及返回。拷貝構(gòu)造函數(shù)要調(diào)用基類的拷貝構(gòu)造函數(shù)和成員函數(shù)。如果可以的話,它將用常量方式調(diào)用,另外,也可以用非常量方式調(diào)用。

              在C++中,下面三種對象需要調(diào)用拷貝構(gòu)造函數(shù):

              1) 一個對象以值傳遞的方式傳入函數(shù)體;

              2) 一個對象以值傳遞的方式從函數(shù)返回;

              3) 一個對象需要通過另外一個對象進(jìn)行初始化;

              如果在前兩種情況不使用拷貝構(gòu)造函數(shù)的時候,就會導(dǎo)致一個指針指向已經(jīng)被刪除的內(nèi)存空間。對于第三種情況來說,初始化和賦值的不同含義是構(gòu)造函數(shù)調(diào)用的原因。事實上,拷貝構(gòu)造函數(shù)是由普通構(gòu)造函數(shù)和賦值操作符共同實現(xiàn)的。描述拷貝構(gòu)造函數(shù)和賦值運算符的異同的參考資料有很多。

              拷貝構(gòu)造函數(shù)不可以改變它所引用的對象,其原因如下:當(dāng)一個對象以傳遞值的方式傳一個函數(shù)的時候,拷貝構(gòu)造函數(shù)自動的被調(diào)用來生成函數(shù)中的對象。如果一個對象是被傳入自己的拷貝構(gòu)造函數(shù),它的拷貝構(gòu)造函數(shù)將會被調(diào)用來拷貝這個對象這樣復(fù)制才可以傳入它自己的拷貝構(gòu)造函數(shù),這會導(dǎo)致無限循環(huán)直至棧溢出(Stack Overflow)。除了當(dāng)對象傳入函數(shù)的時候被隱式調(diào)用以外,拷貝構(gòu)造函數(shù)在對象被函數(shù)返回的時候也同樣的被調(diào)用。

              如果在類中沒有顯式的聲明一個拷貝構(gòu)造函數(shù),那么,編譯器會自動生成一個來進(jìn)行對象之間的位拷貝(Bitwise Copy)。這個隱含的拷貝構(gòu)造函數(shù)簡單的關(guān)聯(lián)了所有的類成員。注意到這個隱式的拷貝構(gòu)造函數(shù)和顯式聲明的拷貝構(gòu)造函數(shù)的不同在于對成員的關(guān)聯(lián)方式。顯式聲明的拷貝構(gòu)造函數(shù)關(guān)聯(lián)的只是被實例化的類成員的缺省構(gòu)造函數(shù),除非另外一個構(gòu)造函數(shù)在類初始化或構(gòu)造列表的時候被調(diào)用。

              拷貝構(gòu)造函數(shù)使程序更有效率,因為它不用再構(gòu)造一個對象的時候改變構(gòu)造函數(shù)的參數(shù)列表。設(shè)計拷貝構(gòu)造函數(shù)是一個良好的風(fēng)格,即使是編譯系統(tǒng)會自動為你生成默認(rèn)拷貝構(gòu)造函數(shù)。事實上,默認(rèn)拷貝構(gòu)造函數(shù)可以應(yīng)付許多情況。

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

              class CExample

              {

              public:

              CExample(){pBuffer=NULL; nSize=0;}

              ~CExample(){delete pBuffer;}

              void Init(int n){ pBuffer=new char[n]; nSize=n;}

              private:

              char *pBuffer; //類的對象中包含指針,指向動態(tài)分配的內(nèi)存資源

              int nSize;

              };

              這個類的主要特點是包含指向其他資源的指針。

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

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

              int main(int argc, char* argv[])

              {

              CExample theObjone;

              theObjone.Init(40);

              //現(xiàn)在需要另一個對象,需要將他初始化稱對象一的狀態(tài)

              CExample theObjtwo=theObjone;

              ...

              }

              語句"CExample theObjtwo=theObjone;"theObjone初始化theObjtwo

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

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

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

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

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

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

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

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

              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; //類的對象中包含指針,指向動態(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));

              }

              這樣,定義新對象,并用已有對象初始化新對象時,CExample(const CExample& RightSides)將被調(diào)用,而已有對象用別名RightSides傳給構(gòu)造函數(shù),以用來作復(fù)制。原則上,應(yīng)該為所有包含動態(tài)分配成員的類都提供拷貝構(gòu)造函數(shù)。

              下面介紹拷貝構(gòu)造函數(shù)的另一種調(diào)用。當(dāng)對象直接作為參數(shù)傳給函數(shù)時,函數(shù)將建立對象的臨時拷貝,這個拷貝過程也將調(diào)同拷貝構(gòu)造函數(shù)。例如:

              BOOL testfunc(CExample obj);

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

              BOOL testfunc(CExample obj)

              {

              //針對obj的操作實際上是針對復(fù)制后的臨時拷貝進(jìn)行的

              }

              還有一種情況,也是與臨時對象有關(guān)的

              當(dāng)函數(shù)中的局部對象被被返回給函數(shù)調(diào)者時,也將建立此局部對象的一個臨時拷貝,拷貝構(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)在需要一個對象賦值操作,被賦值對象的原內(nèi)容被清除,并用右邊對象的內(nèi)容填充。

              theObjthree=theObjone;

              return 0;

              }

              也用到了"="號,但與"一、"中的例子并不同,"一、"的例子中,"="在對象聲明語句中,表示初始化。更多時候,這種初始化也可用括號表示。

              例如 CExample theObjone(theObjtwo);

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

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

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

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

              類定義變?yōu)?span lang="EN-US">:

              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=NULL;

              pBuffer=temp; //建立新指向

              return *this

              }

              三、注意事項

              常見錯誤:

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

              CExample::CExample(const CExample& RightSides)

              {

              *this=RightSides //調(diào)用重載后的"="

              }

              而這樣會造成循環(huán)調(diào)用重載后的"="和拷貝構(gòu)造函數(shù),最后造成棧溢出(Stack Overflow)

              四,拷貝構(gòu)造函數(shù)與構(gòu)造函數(shù)的區(qū)別

              class 類名

              {

              public

              類名(形參參數(shù))//構(gòu)造函數(shù)

              類名(類名&對象名)//拷貝構(gòu)造函數(shù)

              ,,,,,,,,,,,,,,,,,,,,,

              };

              拷貝構(gòu)造函數(shù)的實現(xiàn):

              類名::類名(類名&對象名)//拷貝構(gòu)造函數(shù)的實現(xiàn)

              {函數(shù)體}

              不完整的例子

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

              Class Point

              {

              Public:

              Point(int xx=0,int yy=m)(X=xx;Y=yy;)

              Point(Point& p);

              Int getX() {return X}

              Int getY(){ return Y;}

              Private :

              Int X,Y;

              }

              Point::Point(Point& p)

              {

              X=p.X;

              Y=p.Y;

              Cout<<"拷貝構(gòu)造函數(shù)吊樣"<<endl;

              }

            posted on 2009-01-22 12:18 肥仔 閱讀(582) 評論(0)  編輯 收藏 引用 所屬分類: C++ 基礎(chǔ)

            亚洲午夜精品久久久久久浪潮| 久久九九精品99国产精品| 精品久久综合1区2区3区激情| 26uuu久久五月天| 久久久久久精品免费看SSS| 国产V综合V亚洲欧美久久| 精品国产热久久久福利| 精品久久久久成人码免费动漫| 亚洲精品tv久久久久久久久| 国产精品久久永久免费| 欧美国产精品久久高清| 久久国产精品一区二区| 欧美亚洲另类久久综合婷婷| 精品熟女少妇a∨免费久久| 日韩久久无码免费毛片软件| 久久久青草青青亚洲国产免观| 一97日本道伊人久久综合影院| 国产午夜福利精品久久2021| 国产精品一区二区久久精品涩爱| 久久精品国产精品青草| 亚洲国产精品无码成人片久久| 久久www免费人成精品香蕉| 久久精品亚洲精品国产色婷| 中文字幕无码av激情不卡久久| 国产AⅤ精品一区二区三区久久| 亚洲国产精品一区二区久久hs| 久久这里有精品视频| 99久久精品国产麻豆| 久久男人Av资源网站无码软件| 精品国产99久久久久久麻豆| 久久久久婷婷| 99久久精品九九亚洲精品| 久久久久中文字幕| 久久香蕉国产线看观看99| 久久精品人人槡人妻人人玩AV| 久久99精品久久久大学生| 国产美女亚洲精品久久久综合| 日韩欧美亚洲综合久久影院Ds| 色综合久久88色综合天天 | 久久精品二区| 亚洲精品午夜国产va久久|