C++ 深拷貝和淺拷貝
1.淺拷貝與深拷貝的區(qū)別
淺拷貝(默認拷貝函數(shù)):將原對象或原數(shù)組的引用直接賦給新對象,新數(shù)組,新對象/新數(shù)組只是原對象的一個引用。
深拷貝:創(chuàng)建一個新的對象和數(shù)組,將原對象的各項屬性的“值”(數(shù)組的所有元素)拷貝過來,是“值”而不是引用
深拷貝會在堆內(nèi)存中另外申請空間來儲存數(shù)據(jù),從而解決了指針懸掛問題。當數(shù)據(jù)成員中有指針時,必須要用深拷貝。
(1)如果拷貝的對象里的元素只有值,沒有引用,那么深拷貝與淺拷貝是相同的。
都會對原有對象復制一份,產(chǎn)生一個新對象,對新對象里的值進行修改不會影響原有對象,新對象與原對象完全分離開。
(2)如果拷貝的對象里的元素包含引用(像一個列表中儲存著另一個列表,存的就是另一個列表的引用),那么淺拷貝和深拷貝是不同的。
淺拷貝雖然將原有對象復制一份,但是依然保存的是引用,所以對新對象里的引用里的值進行修改,依然會改變原對象里的列表的值,新對象與原對象并沒有完全分離開。
深拷貝不同,它會將原對象里的引用也新創(chuàng)建一個,即新建一個列表,然后放的是新列表的引用,這樣就可以將新對象和原對象完全分開。
2.為什么要用深拷貝
在改變新的數(shù)組(對象)時,不會改變原數(shù)組(對象)
3.有指針時,必須用深拷貝
當數(shù)據(jù)成員中含有指針時,必須用深拷貝
當用淺拷貝時,新對象的指針與原對象的指針指向了堆上的同一塊兒內(nèi)存,新對象和原對象析構(gòu)時,新對象先把其指向的動態(tài)分配的內(nèi)存釋放了一次,而后原對象析構(gòu)時又將這塊已經(jīng)釋放過的內(nèi)存再釋放一次。對同一塊動態(tài)內(nèi)存執(zhí)行2次以上釋放的結(jié)果是未定義的,所有會導致內(nèi)存泄漏或程序崩潰。
所以需要深拷貝來解決問題,當拷貝對象中有對其他資源(如堆、文件、系統(tǒng)等)的引用時(引用可以是指針或引用)時,對象開辟一塊新的資源,而不再對拷貝對象中對其他資源的引用的指針或引用進行單純的賦值。