构造函数,拷贝构造函数,赋值函数
? ? C++中一般創(chuàng)建對象,拷貝或賦值的方式有構(gòu)造函數(shù),拷貝構(gòu)造函數(shù),賦值函數(shù)這三種方法。下面就詳細比較下三者之間的區(qū)別以及它們的具體實現(xiàn)
1.構(gòu)造函數(shù)
構(gòu)造函數(shù)是一種特殊的類成員函數(shù),是當(dāng)創(chuàng)建一個類的對象時,它被調(diào)用來對類的數(shù)據(jù)成員進行初始化和分配內(nèi)存。(構(gòu)造函數(shù)的命名必須和類名完全相同)
首先說一下一個C++的空類,編譯器會加入哪些默認的成員函數(shù)
·默認構(gòu)造函數(shù)和拷貝構(gòu)造函數(shù)
·析構(gòu)函數(shù)
·賦值函數(shù)(賦值運算符)
·取值函數(shù)
**即使程序沒定義任何成員,編譯器也會插入以上的函數(shù)!?
?
注意:構(gòu)造函數(shù)可以被重載,可以多個,可以帶參數(shù);
析構(gòu)函數(shù)只有一個,不能被重載,不帶參數(shù)
?
而默認構(gòu)造函數(shù)沒有參數(shù),它什么也不做。當(dāng)沒有重載無參構(gòu)造函數(shù)時,
? A a就是通過默認構(gòu)造函數(shù)來創(chuàng)建一個對象
下面代碼為構(gòu)造函數(shù)重載的實現(xiàn)
[cpp]?view plain?copy
?
2.拷貝構(gòu)造函數(shù)
?
拷貝構(gòu)造函數(shù)是C++獨有的,它是一種特殊的構(gòu)造函數(shù),用基于同一類的一個對象構(gòu)造和初始化另一個對象。
當(dāng)沒有重載拷貝構(gòu)造函數(shù)時,通過默認拷貝構(gòu)造函數(shù)來創(chuàng)建一個對象
A a;
A b(a);
A b=a; ?都是拷貝構(gòu)造函數(shù)來創(chuàng)建對象b
強調(diào):這里b對象是不存在的,是用a 對象來構(gòu)造和初始化b的!!
?
先說下什么時候拷貝構(gòu)造函數(shù)會被調(diào)用:
在C++中,3種對象需要復(fù)制,此時拷貝構(gòu)造函數(shù)會被調(diào)用
1)一個對象以值傳遞的方式傳入函數(shù)體
2)一個對象以值傳遞的方式從函數(shù)返回
3)一個對象需要通過另一個對象進行初始化
?
什么時候編譯器會生成默認的拷貝構(gòu)造函數(shù):
1)如果用戶沒有自定義拷貝構(gòu)造函數(shù),并且在代碼中使用到了拷貝構(gòu)造函數(shù),編譯器就會生成默認的拷貝構(gòu)造函數(shù)。但如果用戶定義了拷貝構(gòu)造函數(shù),編譯器就不在生成。
2)如果用戶定義了一個構(gòu)造函數(shù),但不是拷貝構(gòu)造函數(shù),而此時代碼中又用到了拷貝構(gòu)造函數(shù),那編譯器也會生成默認的拷貝構(gòu)造函數(shù)。
?
因為系統(tǒng)提供的默認拷貝構(gòu)造函數(shù)工作方式是內(nèi)存拷貝,也就是淺拷貝。如果對象中用到了需要手動釋放的對象,則會出現(xiàn)問題,這時就要手動重載拷貝構(gòu)造函數(shù),實現(xiàn)深拷貝。
下面說說深拷貝與淺拷貝:
淺拷貝:如果復(fù)制的對象中引用了一個外部內(nèi)容(例如分配在堆上的數(shù)據(jù)),那么在復(fù)制這個對象的時候,讓新舊兩個對象指向同一個外部內(nèi)容,就是淺拷貝。(指針雖然復(fù)制了,但所指向的空間內(nèi)容并沒有復(fù)制,而是由兩個對象共用,兩個對象不獨立,刪除空間存在)
深拷貝:如果在復(fù)制這個對象的時候為新對象制作了外部對象的獨立復(fù)制,就是深拷貝。
?
拷貝構(gòu)造函數(shù)重載聲明如下:?
?
A (const A&other)
下面為拷貝構(gòu)造函數(shù)的實現(xiàn):
[cpp]?view plain?copy
?
3.賦值函數(shù)
當(dāng)一個類的對象向該類的另一個對象賦值時,就會用到該類的賦值函數(shù)。
當(dāng)沒有重載賦值函數(shù)(賦值運算符)時,通過默認賦值函數(shù)來進行賦值操作
A a;
A b;
b=a;?
強調(diào):這里a,b對象是已經(jīng)存在的,是用a 對象來賦值給b的!!
?
賦值運算的重載聲明如下:
?A& operator = (const A& other)
?
通常大家會對拷貝構(gòu)造函數(shù)和賦值函數(shù)混淆,這兒仔細比較兩者的區(qū)別:
1)拷貝構(gòu)造函數(shù)是一個對象初始化一塊內(nèi)存區(qū)域,這塊內(nèi)存就是新對象的內(nèi)存區(qū),而賦值函數(shù)是對于一個已經(jīng)被初始化的對象來進行賦值操作。
[cpp]?view plain?copy
?
2)一般來說在數(shù)據(jù)成員包含指針對象的時候,需要考慮兩種不同的處理需求:一種是復(fù)制指針對象,另一種是引用指針對象??截悩?gòu)造函數(shù)大多數(shù)情況下是復(fù)制,而賦值函數(shù)是引用對象
3)實現(xiàn)不一樣??截悩?gòu)造函數(shù)首先是一個構(gòu)造函數(shù),它調(diào)用時候是通過參數(shù)的對象初始化產(chǎn)生一個對象。賦值函數(shù)則是把一個新的對象賦值給一個原有的對象,所以如果原來的對象中有內(nèi)存分配要先把內(nèi)存釋放掉,而且還要檢察一下兩個對象是不是同一個對象,如果是,不做任何操作,直接返回。(這些要點會在下面的String實現(xiàn)代碼中體現(xiàn))
?
!!!如果不想寫拷貝構(gòu)造函數(shù)和賦值函數(shù),又不允許別人使用編譯器生成的缺省函數(shù),最簡單的辦法是將拷貝構(gòu)造函數(shù)和賦值函數(shù)聲明為私有函數(shù),不用編寫代碼。如:
[cpp]?view plain?copy
如果程序這樣寫就會出錯:
[cpp]?view plain?copy
?
所以如果類定義中有指針或引用變量或?qū)ο?#xff0c;為了避免潛在錯誤,最好重載拷貝構(gòu)造函數(shù)和賦值函數(shù)。
?
下面以string類的實現(xiàn)為例,完整的寫了普通構(gòu)造函數(shù),拷貝構(gòu)造函數(shù),賦值函數(shù)的實現(xiàn)。String類的基本實現(xiàn)見我另一篇博文。
[cpp]?view plain?copy
?
?
一句話記住三者:對象不存在,且沒用別的對象來初始化,就是調(diào)用了構(gòu)造函數(shù);
??????????????? 對象不存在,且用別的對象來初始化,就是拷貝構(gòu)造函數(shù)(上面說了三種用它的情況!)
???????????????? 對象存在,用別的對象來給它賦值,就是賦值函數(shù)。
?
總結(jié)
以上是生活随笔為你收集整理的构造函数,拷贝构造函数,赋值函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++常用的容器(vector、set、
- 下一篇: “引用作为函数参数”与 “引用作为函数返