真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

什么是拷貝構(gòu)造函數(shù)-創(chuàng)新互聯(lián)

本篇文章給大家分享的是有關(guān)什么是拷貝構(gòu)造函數(shù),小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。

創(chuàng)新互聯(lián)堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的尉氏網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

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

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

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

目錄

  • 1、拷貝構(gòu)造函數(shù)概述

  • 2、拷貝構(gòu)造函數(shù)例述

  • 3、賦值操作符的重載

  • 4、拷貝構(gòu)造函數(shù)的格式與示例

  • 展開(kāi)

  • 1、拷貝構(gòu)造函數(shù)概述

  • 2、拷貝構(gòu)造函數(shù)例述

  • 3、賦值操作符的重載

  • 4、拷貝構(gòu)造函數(shù)的格式與示例

  • 展開(kāi)

編輯本段1、拷貝構(gòu)造函數(shù)概述

調(diào)用拷貝構(gòu)造函數(shù)的情形

在C++中,下面三種對(duì)象需要調(diào)用拷貝構(gòu)造函數(shù)(有時(shí)也稱“復(fù)制構(gòu)造函數(shù)”):

1) 一個(gè)對(duì)象作為函數(shù)參數(shù),以值傳遞的方式傳入函數(shù)體;

2) 一個(gè)對(duì)象作為函數(shù)返回值,以值傳遞的方式從函數(shù)返回;

3) 一個(gè)對(duì)象用于給另外一個(gè)對(duì)象進(jìn)行初始化(常稱為復(fù)制初始化);

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

通常的原則是:①對(duì)于凡是包含動(dòng)態(tài)分配成員或包含指針成員的類都應(yīng)該提供拷貝構(gòu)造函數(shù);②在提供拷貝構(gòu)造函數(shù)的同時(shí),還應(yīng)該考慮重載"="賦值操作符號(hào)。原因詳見(jiàn)后文。

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

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

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

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

編輯本段2、拷貝構(gòu)造函數(shù)例述

復(fù)制初始化

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

class CExample

{

public:

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

~CExample(){delete []pBuffer;}

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

private:

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

int nSize;

};

這個(gè)類的主要特點(diǎn)是包含指向其他資源的指針,pBuffer指向堆中動(dòng)態(tài)分配的一段內(nèi)存空間。

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

{

CExample theObjone;

theObjone.Init(40);

//現(xiàn)在需要另一個(gè)對(duì)象,并將它初始化為theObjone

CExample theObjtwo=theObjone;

...

}

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

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

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

即它們將指向同樣的地方,指針雖然復(fù)制了,但所指向的空間并沒(méi)有復(fù)制,而是由兩個(gè)對(duì)象共用了。這樣不符合要求,對(duì)象之間不獨(dú)立了,并為空間的刪除帶來(lái)隱患。所以需要采用必要的手段來(lái)避免此類情況:可以在構(gòu)造函數(shù)中添加操作來(lái)解決指針成員的這種問(wèn)題。

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

拷貝構(gòu)造函數(shù)的格式為:類名(const 類名& 對(duì)象名);//拷貝構(gòu)造函數(shù)的原型,參數(shù)是常量對(duì)象的引用。由于拷貝構(gòu)造函數(shù)的目的是成員復(fù)制,不應(yīng)修改原對(duì)象,所以建議使用const關(guān)鍵字

提供了拷貝構(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; //類的對(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ù)制。

對(duì)象按值傳遞

下面介紹拷貝構(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;

}

總結(jié):當(dāng)某對(duì)象是按值傳遞時(shí)(無(wú)論是作為函數(shù)參數(shù),還是作為函數(shù)返回值),編譯器都會(huì)先建立一個(gè)此對(duì)象的臨時(shí)拷貝,而在建立該臨時(shí)拷貝時(shí)就會(huì)調(diào)用類的拷貝構(gòu)造函數(shù)。

編輯本段3、賦值操作符的重載

重載的必要性

下面的代碼與上例相似

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),但與"復(fù)制初始化"中的例子并不同。"復(fù)制初始化"的例子中,"="在對(duì)象聲明語(yǔ)句中,表示初始化。更多時(shí)候,這種初始化也可用圓括號(hào)表示。例如:CExample theObjthree(theObjone);。

而本例子中,"="表示賦值操作。將對(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)分配成員的類除提供拷貝構(gòu)造函數(shù)外,還應(yīng)該考慮重載"="賦值操作符號(hào)。

重載的示例

類定義變?yōu)?

class CExample

{

public:

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

~CExample(){delete pBuffer;}

CExample(const CExample&); //拷貝構(gòu)造函數(shù)

CExample& operator = (const CExample&); //賦值符重載

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

private:

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

int nSize;

};

//賦值操作符重載

CExample& CExample::operator = (const CExample& RightSides)

{

if (this == &RightSides) // 如果自己給自己賦值則直接返回

{return *this;}

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ù)和賦值函數(shù)的功能是相同的,為了不造成重復(fù)代碼,拷貝構(gòu)造函數(shù)實(shí)現(xiàn)如下:

CExample::CExample(const CExample& RightSides)

{

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

}

編輯本段4、拷貝構(gòu)造函數(shù)的格式與示例

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

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

class 類名

{

public:

類名(形參參數(shù))//構(gòu)造函數(shù)的聲明/原型

類名(類名&對(duì)象名)//拷貝構(gòu)造函數(shù)的聲明/原型

...

};

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

類名::類名(類名&對(duì)象名)//拷貝構(gòu)造函數(shù)的實(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ù)調(diào)用"<

}

以上就是什么是拷貝構(gòu)造函數(shù),小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


分享標(biāo)題:什么是拷貝構(gòu)造函數(shù)-創(chuàng)新互聯(lián)
URL標(biāo)題:http://weahome.cn/article/cspddd.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部