深度拷貝和潛拷貝

2021-06-26 05:34:37 字數 4326 閱讀 9260

淺 復 制:在複製操作時,對於被複製的物件的每一層複製都是指標複製。

深 復 制:在複製操作時,對於被複製的物件至少有一層複製是物件複製。

完全複製:在複製操作時,對於被複製的物件的每一層複製都是物件複製。

注:1、在複製操作時,對於物件有n層是物件複製,我們可稱作n級深複製,此處n應大於等於1。

2、對於完全複製如何實現(目前通用的辦法是:迭代法和歸檔),這裡後續是否新增視情況而定,

暫時不做講解。

3、指標複製俗稱指標拷貝,物件複製也俗稱內容拷貝。

retain:始終是淺複製。引用計數每次加一。返回物件是否可變與被複製的物件保持一致。

copy:對於可變物件為深複製,引用計數不改變;

對於不可變物件是淺複製,

引用計數每次加一。始終返回乙個不可變物件。

mutablecopy:始終是深複製,引用計數不改變。始終返回乙個可變物件。

#import

int main (int argc, const char * argv)

return 0;

}如果容器類想實現完全深度用nscoding協議實現

nsarray *arr = [nsarray arraywithobjects:people, nil];

nsdata *data = [nskeyedarchiver archiveddatawithrootobject:arr];

nsarray *arr1 = [nskeyedunarchiver unarchiveobjectwithdata:data];

ios 深淺拷貝學習

首先我們需要有這樣的乙個前提:

[array addobject:obj];

這樣obj的引用計數會增加1,如果使用remove則obj的引用計數會減一。

ios對集合的記憶體處理就是這樣的。

那麼,假設obj只被array擁有:

id temp = [array objectatindex:0];

[array removeobjectatindex:0];

如果你再要使用temp就會出錯,因為這個時候obj已經被釋放了。

(提醒一下,如果用nsstring做測試,要注意@「abc」是常量 :-)  )

由於在程式中經常會遇到集合類的傳值,所以,簡單的retain未必夠用,需要對集合內容的拷貝,也就是深拷貝。

下面我們就來**一下。

ios提供了copy和mutablecopy方法,顧名思義,copy就是複製了乙個imutable的物件,而mutablecopy就是複製了乙個mutable的物件。以下將舉幾個例子來說明。

1.     系統的非容器類物件

這裡指的是nsstring,nsnumber等等一類的物件。

nsstring *string = @"origion";

nsstring *stringcopy = [string copy];

nsmutablestring *stringmcopy = [string mutablecopy];

再看下面的例子:

nsmutablestring *string = [nsmutablestring stringwithstring: @"origion"];

nsstring *stringcopy = [string copy];

nsmutablestring *mstringcopy = [string copy];

nsmutablestring *stringmcopy = [string mutablecopy];

以上四個nsstring物件所分配的記憶體都是不一樣的。但是對於mstringcopy其實是個imutable物件,所以上述會報錯。

對於系統的非容器類物件,我們可以認為,如果對一不可變物件複製,copy是指標複製(淺拷貝)和mutablecopy就是物件複製(深拷貝)。如果是對可變物件複製,都是深拷貝,但是copy返回的物件是不可變的。

2.     系統的容器類物件

指nsarray,nsdictionary等。對於容器類本身,上面討論的結論也是適用的,需要**的是複製後容器內物件的變化。

//copy返回不可變物件,mutablecopy返回可變物件

nsarray *array1 = [nsarray arraywithobjects:@"a",@"b",@"c",nil];

nsarray *arraycopy1 = [array1 copy];

//arraycopy1是和array同乙個nsarray物件(指向相同的物件),包括array裡面的元素也是指向相同的指標

nslog(@"array1 retain count: %d",[array1 retaincount]);

nslog(@"array1 retain count: %d",[arraycopy1 retaincount]);

nsmutablearray *marraycopy1 = [array1 mutablecopy];

//marraycopy1是array1的可變副本,指向的物件和array1不同,但是其中的元素和array1中的元素指向的是同乙個物件。marraycopy1還可以修改自己的物件

[marraycopy1 addobject:@"de"];

[marraycopy1 removeobjectatindex:0];

array1和arraycopy1是指標複製,而marraycopy1是物件複製,marraycopy1還可以改變陣列內的元素:刪除或新增。但是注意的是,容器內的元素內容都是指標複製。

下面用另乙個例子來測試一下。

nsarray *marray1 = [nsarray arraywithobjects:[nsmutablestring stringwithstring:@"a"],@"b",@"c",nil];

nsarray *marraycopy2 = [marray1 copy];

nslog(@"marray1 retain count: %d",[marray1 retaincount]);

nsmutablearray *marraymcopy1 = [marray1 mutablecopy];

nslog(@"marray1 retain count: %d",[marray1 retaincount]);

//marraycopy2,marraymcopy1和marray1指向的都是不一樣的物件,但是其中的元素都是一樣的物件——同乙個指標

//一下做測試

nsmutablestring *teststring = [marray1 objectatindex:0];

//teststring = @"1a1";//這樣會改變teststring的指標,其實是將@「1a1」臨時物件賦給了teststring

nsarray *array = [nsarray arraywithobjects:[nsmutablestring stringwithstring:@"first"],[nsstringstringwithstring:@"b"],@"c",nil];

nsarray *deepcopyarray=[[nsarray alloc] initwitharray: array copyitems: yes];//對於array 巢狀array的情況 只能深層複製第一層

nsarray* truedeepcopyarray = [nskeyedunarchiver unarchiveobjectwithdata:

[nskeyedarchiver archiveddatawithrootobject: array]];

或者我們自己實現深拷貝的方法(略)。

3.     自定義物件

如果是我們定義的物件,那麼我們自己要實現nscopying,nsmutablecopying這樣就能呼叫copy和mutablecopy了。舉個例子:

@inte***ce myobj : nsobject

@property (nonatomic, retain) nsmutablestring *name;

@property (nonatomic, retain) nsstring *imutablestr;

@property (nonatomic) int age;

@end

@implementation myobj

@synthesize name;

@synthesize age;

@synthesize imutablestr;

- (id)init

return self;

}- (void)dealloc

- (id)copywithzone:(nszone *)zone

- (id)mutablecopywithzone:(nszone *)zone

@end

深度拷貝和淺度拷貝

文字說明 比如乙個陣列 array 淺度拷貝是當陣列a變數成陣列b的時候,b改變裡面的陣列數值的時候,a也隨著改變,深度拷貝是噹噹陣列a變數成陣列b的時候,b改變裡面的陣列數值的時候,a裡面的陣列陣列不隨著改變,那麼為什麼淺度拷貝會改變a的陣列值而深度拷貝則不會呢?因為淺度拷貝指向的是同乙個記憶體,...

C 預設拷貝建構函式 深度拷貝和淺拷貝

c 類的中有兩個特殊的建構函式,1 無參建構函式,2 拷貝建構函式。它們的特殊之處在於 1 當類中沒有定義任何建構函式時,編譯器會預設提供乙個無參建構函式且其函式體為空 2 當類中沒有定義拷貝建構函式時,編譯器會預設提供乙個拷貝建構函式,進行成員變數之間的拷貝。這個拷貝操作是淺拷貝 這裡只講拷貝建構...

結構體的深度拷貝和淺拷貝

具體 和注釋 define crt secure no warnings include include include typedef struct teacher teacher 編譯器的 號操作,只會把指標變數的值,從from copy 到 to,但 不會 把指標變數 所指 的 記憶體空間 給...