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

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

c其他語言拷貝構(gòu)造函數(shù) C++拷貝構(gòu)造函數(shù)

關(guān)于C++拷貝構(gòu)造函數(shù)的問題

Test?c(Test());//這是函數(shù)聲明,等價(jià)于Test?c(Test(*func)());即接受一個(gè)函數(shù)指針,返回Test對(duì)象的函數(shù)

我們提供的服務(wù)有:成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、雨山ssl等。為近1000家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的雨山網(wǎng)站制作公司

Test?d(Test?const());//這也只是函數(shù)聲明而已,大致上和上面一個(gè)聲明同義

前段時(shí)間被這種惡心的解析規(guī)則坑過,教訓(xùn)就是不要畫蛇添足地寫上Test(),Test?c就能完成需要的效果

C++拷貝構(gòu)造函數(shù)屬于構(gòu)造函數(shù)的一種嗎

拷貝構(gòu)造是構(gòu)造函數(shù)的一種.

它的原理是函數(shù)的重載.

選擇參數(shù)類型一樣的函數(shù)進(jìn)行操作.

如果有兩個(gè)參數(shù)一樣的(拷貝)構(gòu)造函數(shù),它就會(huì)出錯(cuò),不知道為選擇那一個(gè).

void?main()

{

Point?a(4,2)?//調(diào)用構(gòu)造函數(shù)?//正確

Point?b(a);?//調(diào)用復(fù)制構(gòu)造函數(shù),不調(diào)用構(gòu)造函數(shù)?//正確

Point?c(7,8);?//調(diào)用構(gòu)造函數(shù)?//正確

}

拷貝構(gòu)造函數(shù)、構(gòu)造函數(shù)和賦值語句的區(qū)別

class CStr

{

public:

CStr(); //默認(rèn)構(gòu)造函數(shù)

CStr(const char* psz); //一種廣義拷貝構(gòu)造函數(shù)

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

const CStr operator=(const CStr str); //賦值構(gòu)造函數(shù)

size_t GetSize() const; //這里的const是什么意思?它必須嗎?

operator const char*() const { return m_pdata; }

protected:

const CStr* _Copy(const CStr str);

private:

char* m_pdata;

size_t m_size;

};

CStr::CStr()

{

m_pdata = NULL;

m_size = 0;

}

size_t CStr::GetSize() const

{

return m_size;

}

const CStr* CStr::_Copy(const CStr str)

{

if(this != str)

{

if(m_pdata){

delete[] m_pdata;

}

m_size = str.GetSize();

m_pdata = new char[m_size + 1]; assert(m_pdata);

strcpy(m_pdata, str);

}

return this;

}

CStr::CStr(const char* psz) : m_pdata(NULL), m_size(0)

{

assert(psz);

if(m_pdata != psz)

{

if(m_pdata){

delete[] m_pdata;

}

m_size = strlen(psz);

m_pdata = new char[m_size + 1]; assert(m_pdata);

strcpy(m_pdata, psz);

}

}

CStr::CStr(const CStr str): m_pdata(NULL), m_size(0)

{

_Copy(str);

}

const CStr CStr::operator=(const CStr str)

{

return *(_Copy(str));

}

int main()

{

const char* psz = "test";

const char* psz1 = "me";

CStr str(psz); //拷貝構(gòu)造函數(shù),此處調(diào)用的是CStr(const char* psz)。 #1

CStr str2(str); // 拷貝構(gòu)造函數(shù),此處調(diào)用的是 CStr(const CStr str) #2

CStr str1 = psz1; // 拷貝構(gòu)造,str1此前并不存在,現(xiàn)在要先構(gòu)造它。 #3

str = str1; // 真正的賦值構(gòu)造函數(shù) #4

return 0;

}

上面這個(gè)小型的例子,主要就是為了闡述賦值構(gòu)造函數(shù)與拷貝構(gòu)造函數(shù)之間的區(qū)別,其實(shí),賦值構(gòu)造函數(shù)不應(yīng)該被稱為一個(gè)構(gòu)造函數(shù),充其量只能算得上一個(gè)重載的操作符函數(shù)。

在C語言中,我們知道"=="是判等操作符,而"="卻是一個(gè)賦值操作符,所以只要沒有出現(xiàn)"="操作符,也就不會(huì)有賦值操作可言。

在調(diào)用賦值構(gòu)造函數(shù)的時(shí)候,類對(duì)象已經(jīng)存在,自然談不上構(gòu)造類對(duì)象,它只是對(duì)該已經(jīng)存在的類對(duì)象的成員變量進(jìn)行修改(所謂的賦值)操作。而拷貝構(gòu)造函數(shù)是利用一個(gè)已經(jīng)存在的類對(duì)象構(gòu)造出一個(gè)新的類對(duì)象。

回到上面的例子,相信大多數(shù)人都應(yīng)該能分清#1、#2、#4所調(diào)用的函數(shù),而對(duì)于#3,賦值構(gòu)造的實(shí)際用意是修改一個(gè)已有的對(duì)象,而現(xiàn)在str1還沒有被定義,所以此處還是必須要調(diào)用拷貝構(gòu)造函數(shù)先產(chǎn)生一個(gè)CStr對(duì)象。

最后,定義與賦值同時(shí)進(jìn)行的話,必須要先定義,所以必須得先調(diào)用拷貝構(gòu)造函數(shù),而對(duì)于符合單純的賦值操作語法的語句(也就是只有兩個(gè)操作數(shù)的表達(dá)式)來說,才是真正的調(diào)用賦值構(gòu)造函數(shù)。

C++中,拷貝構(gòu)造函數(shù),和構(gòu)造函數(shù)有什么區(qū)別?

構(gòu)造函數(shù):是用于對(duì)對(duì)象初始化名字,必須與類的名字相同,比如說定義一個(gè)圓類。

復(fù)制構(gòu)造函數(shù),在某種意義上相當(dāng)于運(yùn)算符“=”重載,把一個(gè)對(duì)象的數(shù)值復(fù)制給另一個(gè)

class circle

{

public:

circle (int r):radium(r){};//構(gòu)造函數(shù)的第一種寫法

circle (int r){radium=r;}//構(gòu)造函數(shù)的第二種寫法

circle(circle c)

{

radium=c.radium;//這樣復(fù)制,在主函數(shù)里用cir1(cir2);這樣使用

}

private:

int radium;

};

C++ 復(fù)制構(gòu)造函數(shù)

拷貝構(gòu)造函數(shù),是一種特殊的構(gòu)造函數(shù),它由編譯器調(diào)用來完成一些基于同一類的其他對(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)用。

目錄

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

一、拷貝函數(shù)

二、值的重載

三、注意事宜

四、拷貝構(gòu)造與構(gòu)造區(qū)別

展開

編輯本段

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

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

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

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

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

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

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

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

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

如果在類中沒有顯式的聲明一個(gè)拷貝構(gòu)造函數(shù),那么,編譯器會(huì)自動(dòng)生成一個(gè)來進(jìn)行對(duì)象之間的位拷貝(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)付許多情況。

示例

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

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指向堆中分配的一段內(nèi)存空間。

編輯本段

一、拷貝函數(shù)

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

{

CExample theObjone;

theObjone.Init(40);

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

CExample theObjtwo=theObjone;

...

}

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

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

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

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

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

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

所以C++語法中除了提供缺省形式的構(gòu)造函數(shù)外,還規(guī)范了另一種特殊的構(gòu)造函數(shù):拷貝構(gòu)造函數(shù),上面的語句中,如果類中定義了拷貝構(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類定義為:

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ù),以用來作復(fù)制。原則上,應(yīng)該為所有包含動(dòng)態(tài)分配成員的類都提供拷貝構(gòu)造函數(shù)。

下面介紹拷貝構(gòu)造函數(shù)的另一種調(diào)用。當(dāng)對(duì)象直接作為參數(shù)傳給函數(shù)時(shí),函數(shù)將建立對(duì)象的臨時(shí)拷貝,這個(gè)拷貝過程也將調(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ì)象聲明語句中,表示初始化。更多時(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)分配成員的類除提供拷貝構(gòu)造函數(shù)外,還應(yīng)該考慮重載"="賦值操作符號(hào)。

類定義變?yōu)?

class CExample

{

...

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

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

...

};

//賦值操作符重載

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

pBuffer=temp; //建立新指向

return *this

}

編輯本段

三、注意事宜

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

CExample::CExample(const CExample RightSides)

{

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

}

編輯本段

四、拷貝構(gòu)造與構(gòu)造區(qū)別

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)用"endl;

}

c語言中的位拷貝是什么意思?C++中有位拷貝這個(gè)說法嗎?它和拷貝構(gòu)造函數(shù)有什么區(qū)別?

位拷貝也叫淺拷貝。。。是編譯器幫你自動(dòng)生成的拷貝構(gòu)造函數(shù)做的事情,它只能做一些基本的賦值操作,如果自己定義拷貝構(gòu)造函數(shù)就要防止位拷貝。。因?yàn)槲豢截惾菀装l(fā)生一些錯(cuò)誤。。


當(dāng)前題目:c其他語言拷貝構(gòu)造函數(shù) C++拷貝構(gòu)造函數(shù)
網(wǎng)站URL:http://weahome.cn/article/docpdpg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部