點(diǎn)擊上方“C語(yǔ)言與CPP編程”,選擇“關(guān)注/置頂/星標(biāo)公眾號(hào)”
干貨福利,第一時(shí)間送達(dá)!
最近有小伙伴說(shuō)沒(méi)有收到當(dāng)天的文章推送,這是因?yàn)槲⑿鸥牧送扑蜋C(jī)制,導(dǎo)致沒(méi)有星標(biāo)公眾號(hào)的小伙伴刷不到當(dāng)天推送的文章,無(wú)法接收到一些比較實(shí)用的知識(shí)和資訊。所以建議大家加個(gè)星標(biāo)??,以后就能第一時(shí)間收到推送了。
C++中類的拷貝有兩種:深拷貝,淺拷貝:當(dāng)出現(xiàn)類的等號(hào)賦值時(shí),即會(huì)調(diào)用拷貝函數(shù)
一:兩個(gè)的區(qū)別
1 在未定義顯示拷貝構(gòu)造函數(shù)的情況下,系統(tǒng)會(huì)調(diào)用默認(rèn)的拷貝函數(shù)——即淺拷貝,它能夠完成成員的一一復(fù)制。當(dāng)數(shù)據(jù)成員中沒(méi)有指針時(shí),淺拷貝是可行的;但當(dāng)數(shù)據(jù)成員中有指針時(shí),如果采用簡(jiǎn)單的淺拷貝,則兩類中的兩個(gè)指針將指向同一個(gè)地址,當(dāng)對(duì)象快結(jié)束時(shí),會(huì)調(diào)用兩次析構(gòu)函數(shù),而導(dǎo)致指針懸掛現(xiàn)象,所以,此時(shí),必須采用深拷貝。
2 深拷貝與淺拷貝的區(qū)別就在于深拷貝會(huì)在堆內(nèi)存中另外申請(qǐng)空間來(lái)儲(chǔ)存數(shù)據(jù),從而也就解決了指針懸掛的問(wèn)題。簡(jiǎn)而言之,當(dāng)數(shù)據(jù)成員中有指針時(shí),必須要用深拷貝。
二 帶實(shí)例的解釋
c++默認(rèn)的拷貝構(gòu)造函數(shù)是淺拷貝
淺拷貝就是對(duì)象的數(shù)據(jù)成員之間的簡(jiǎn)單賦值,如你設(shè)計(jì)了一個(gè)沒(méi)有類而沒(méi)有提供它的復(fù)制構(gòu)造函數(shù),當(dāng)用該類的一個(gè)對(duì)象去給令一個(gè)對(duì)象賦值時(shí)所執(zhí)行的過(guò)程就是淺拷貝,如:
class A
{
public:
A(int _data) : data(_data){}
A(){}
private:
int data;
};
int main()
{
A a(5), b = a; // 僅僅是數(shù)據(jù)成員之間的賦值
}
這一句b = a;就是淺拷貝,執(zhí)行完這句后b.data = 5;
如果對(duì)象中沒(méi)有其他的資源(如:堆,文件,系統(tǒng)資源等),則深拷貝和淺拷貝沒(méi)有什么區(qū)別。
但當(dāng)對(duì)象中有這些資源時(shí),例子:
class A
{
public:
A(int _size) : size(_size)
{
data = new int[size];
} // 假如其中有一段動(dòng)態(tài)分配的內(nèi)存
A(){};
~A()
{
delete [] data;
} // 析構(gòu)時(shí)釋放資源
private:
int* data;
int size;
}
int main()
{
A a(5), b = a; // 注意這一句
}
這里的b = a會(huì)造成未定義行為,因?yàn)轭怉中的復(fù)制構(gòu)造函數(shù)是編譯器生成的,所以b = a執(zhí)行的是一個(gè)淺拷貝過(guò)程。我說(shuō)過(guò)淺拷貝是對(duì)象數(shù)據(jù)之間的簡(jiǎn)單賦值,比如:
b.size = a.size;
b.data = a.data; // Oops!
這里b的指針data和a的指針指向了堆上的同一塊內(nèi)存,a和b析構(gòu)時(shí),b先把其data指向的動(dòng)態(tài)分配的內(nèi)存釋放了一次,而后a析構(gòu)時(shí)又將這塊已經(jīng)被釋放過(guò)的內(nèi)存再釋放一次。對(duì)同一塊動(dòng)態(tài)內(nèi)存執(zhí)行2次以上釋放的結(jié)果是未定義的,所以這將導(dǎo)致內(nèi)存泄露或程序崩潰。
所以這里就需要深拷貝來(lái)解決這個(gè)問(wèn)題,深拷貝指的就是當(dāng)拷貝對(duì)象中有對(duì)其他資源(如堆、文件、系統(tǒng)等)的引用時(shí)(引用可以是指針或引用)時(shí),對(duì)象的另開(kāi)辟一塊新的資源,而不再對(duì)拷貝對(duì)象中有對(duì)其他資源的引用的指針或引用進(jìn)行單純的賦值。如:
class A
{
public:
A(int _size) : size(_size)
{
data = new int[size];
} // 假如其中有一段動(dòng)態(tài)分配的內(nèi)存
A(){};
A(const A& _A) : size(_A.size)
{
data = new int[size];
} // 深拷貝
~A()
{
delete [] data;
} // 析構(gòu)時(shí)釋放資源
private:
int* data;
int size;
}
int main()
{
A a(5), b = a; // 這次就沒(méi)問(wèn)題了
}
總結(jié):深拷貝和淺拷貝的區(qū)別是在對(duì)象狀態(tài)中包含其它對(duì)象的引用的時(shí)候,當(dāng)拷貝一個(gè)對(duì)象時(shí),如果需要拷貝這個(gè)對(duì)象引用的對(duì)象,則是深拷貝,否則是淺拷貝。
轉(zhuǎn)自: https://blog.csdn.net/u010700335/article/details/39830425

1、C++訓(xùn)練營(yíng),來(lái)了!
2、HarmonyOS 學(xué)習(xí)資料分享(無(wú)套路免費(fèi)分享)
我組建了一些社群一起交流,群里有大牛也有小白,如果你有意可以一起進(jìn)群交流。
歡迎你添加我的微信,我拉你進(jìn)技術(shù)交流群。此外,我也會(huì)經(jīng)常在微信上分享一些計(jì)算機(jī)學(xué)習(xí)經(jīng)驗(yàn)以及工作體驗(yàn),還有一些內(nèi)推機(jī)會(huì)。
加個(gè)微信,打開(kāi)另一扇窗
感謝你的分享,點(diǎn)贊,在看三連