深拷貝與淺拷貝 動態記憶體釋放有關

2021-09-06 12:13:25 字數 1446 閱讀 4610

淺拷貝就是物件的資料成員之間的簡單賦值,如你設計了乙個沒有類而沒有提供它的複製建構函式,當用該類的乙個物件去給令乙個物件賦值時所執行的過程就是淺拷貝,如:

class

a a(){}

private: int

data;

};int

main()

這一句b = a;就是淺拷貝,執行完這句後b.data = 5;

如果物件中沒有其他的資源(如:堆,檔案,系統資源等),則深拷貝和淺拷貝沒有什麼區別,

但當物件中有這些資源時,例子:

classa  

//假如其中有一段動態分配的記憶體

a(){};

~a() //

析構時釋放資源

private: int*data;

intsize;

}int

main()

這裡的b = a會造成未定義行為,因為類a中的複製建構函式是編譯器生成的,所以b = a執行的是乙個淺拷貝過程。我說過淺拷貝是物件資料之間的簡單賦值,比如:

b.size = a.size; b.data = a.data; // oops!

這裡b的指標data和a的指標指向了堆上的同一塊記憶體,a和b析構時,b先把其data指向的動態分配的記憶體釋放了一次,而後a析構時又將這塊已經被釋放過的記憶體再釋放一次。

對同一塊動態記憶體執行2次以上釋放的結果是未定義的,所以這將導致記憶體洩露或程式崩潰。

所以這裡就需要深拷貝來解決這個問題,

深拷貝指的就是當拷貝物件中有對其他資源(如堆、檔案、系統等)的引用時(引用可以是指標或引用)時,

物件的另開闢一塊新的資源,而不再對拷貝物件中有對其他資源的引用的指標或引用進行單純的賦值。

如:

classa  

//假如其中有一段動態分配的記憶體

a(){};

a(const a&_a) : size(_a.size) //

深拷貝

~a() //

析構時釋放資源

private: int* data; int

size;

}int

main()

總結:

深拷貝和淺拷貝的區別是在物件狀態中包含其它物件的引用的時候,當拷貝乙個物件時,如果需要拷貝這個物件引用的物件,則是深拷貝,否則是淺拷貝。

在某些狀況下,類內成員變數需要動態開闢堆記憶體,如果實行位拷貝,也就是把物件裡的值完全複製給另乙個物件,如a=b。這時,如果b中有乙個成員變數指標已經申請了記憶體,那a中的那個成員變數也指向同一塊記憶體。這就出現了問題:當b把記憶體釋放了(如:析構),這時a內的指標就是野指標了,出現執行錯誤。

深拷貝和淺拷貝可以簡單理解為:如果乙個類擁有資源,當這個類的物件發生複製過程的時候,資源重新分配,這個過程就是深拷貝,反之,沒有重新分配資源,就是淺拷貝。

有關JS 深拷貝和淺拷貝

首先深複製和淺複製只針對像 object,array 這樣的複雜物件的。簡單來說,淺複製只複製一層物件的屬性,而深複製則遞迴複製了所有層級。淺拷貝 複製一層物件的屬性,並不包括物件裡面的為引用型別的資料,當改變拷貝的物件裡面的引用型別時,源物件也會改變。實現深拷貝的集中方法 1.物件只有一層的話可以...

「淺拷貝」與「深拷貝」

c 中物件的複製就如同 轉殖 用乙個已有的物件快速地複製出多個完全相同的物件。一般而言,以下三種情況都會使用到物件的複製 1 建立乙個新物件,並用另乙個同類的已有物件對新物件進行初始化,例如 cpp view plain copy class rect rect rect1 rect rect2 r...

淺拷貝與深拷貝

淺拷貝 1 2 myclass a,b a b 為了封裝性和解耦,同型別的兩個物件之間進行賦值操作時,所有成員變數被複製,包括私有成員 指標變數。類的成員函式在傳遞或返回物件時都會進行物件複製產生臨時物件,比如函式呼叫時實參變為形參,以及函式返回物件。考慮到效能和使用者要求不同,編譯器不複製物件內部...