Objective C 淺拷貝和深拷貝

2021-06-27 06:33:51 字數 4873 閱讀 2825

iphone開發語言objective-c是一種簡單的計算機語言,簡稱oc,支援複雜南通的物件導向程式設計。objective c語言,通常寫作objc和較少用的objective c或obj-c,是擴充c的物件導向程式設計語言。它主要使用於mac os x和gnustep這兩個使用openstep標準的系統,而在nextstep和openstep中它更是基本語言。objective c可以在gcc運作的系統寫和編譯,因為gcc含objective c的編譯器。

在objectivec 中,什麼是深淺拷貝?深淺拷貝分別指深拷貝和淺拷貝,即mutablecopy和copy方法。

copy複製乙個不可變物件,而mutablecopy複製乙個mutable可變物件。

什麼時候用到深淺拷貝?下面舉幾個例子說明。非容器類物件如nsstring,nsnumber等一類物件  

示例1:

// 非容器類物件     nsstring *str = @"origin string";  

nsstring *strcopy = [str copy];  

nsmutablestring *mstrcopy = [str mutablecopy];  

檢視記憶體可以發現,str和strcopy指向的是同一塊記憶體區域,我們稱之為弱引用(weak reference)。而mstrcopy是真正的複製,系統為其分配了新記憶體空間,儲存從str複製過來的字串值。從最後一行**中修改這些值而不影響str和strcopy中可證明。

示例2:

nsmutablestring *mstr = [nsmutablestring stringwithstring:@"origin"];  

nsstring *strcopy = [mstr copy];  

nsmutablestring *mstrcopy = [mstr copy];  

nsmutablestring *mstrmcopy = [mstr mutablecopy];  

以上四個物件所分配的記憶體都是不一樣的。而且對於mstrcopy,它所指向的其實是乙個imutable物件,是不可改變的,所以會出錯。這點要注意,好好理解。

容器類物件深淺複製

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

示例3

/* 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是物件複製,符合前面示例1討論的結論。marraycopy1可以改變其內的元素:刪除或新增。但容器內的元素內容都是淺拷貝。

示例4

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

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

nsarray *marraycopy2 = [marray1 copy];  

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

// marray1和marraycopy2指向同一物件,retain值+1。  

nsmutablearray *marraymcopy1 = [marray1 mutablecopy];  

nslog(@"marray1 retain count: %d",[marray1 retaincount]);     //marraycopy2和marray1指向的是不一樣的物件,但是其中的元素都是一樣的物件——同乙個指標  

nsmutablestring *teststring = [marray1 objectatindex:0];   

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

示例5

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

nsarray *deepcopyarray=[[nsarray alloc] initwitharray: array copyitems: yes];  

nsarray* truedeepcopyarray = [nskeyedunarchiver unarchiveobjectwithdata:  

[nskeyedarchiver archiveddatawithrootobject: array]]; 

truedeepcopyarray是完全意義上的深拷貝,而deepcopyarray則不是,對於deepcopyarray內的不可變元素其還是指標複製。

或者我們自己實現深拷貝的方法。因為如果容器的某一元素是不可變的,那你複製完後該物件仍舊是不能改變的,因此只需要指標複製即可。除非你對容器內的元素重新賦值,否則指標複製即已足夠。

objectatindex:0]儘管是指向同一塊記憶體,但是我們沒有辦法對其進行修改——因為它是不可改變的。所以指標複製已經足夠。所以這並不是完全意義上的深拷貝。

自己實現深拷貝的方法

nsdictionarymutabledeepcopy.h

8 #import <

foundation /foundation.h>

@inte***ce nsdictionary(mutabledeepcopy)  

- (nsmutabledictionary *)mutabledeepcopy;  

@end  

foundation

>

nsdictionarymutabledeepcopy.m  

#import "nsdictionarymutabledeepcopy.h"  

@implementation nsdictionary(mutabledeepcopy)  

- (nsmutabledictionary *)mutabledeepcopy   

else if ([onevalue respondstoselector:@selector(mutablecopy)])   

if (onecopy == nil)   

[ret setvalue:onecopy forkey:key];  

}  return ret;  

}  @end 

使用類別方法來實現。

自定義物件

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

@inte***ce myobj : nsobject<

nscopying ,nsmutablecopying>

@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  

nscopying

>

小結:

對於非容器類物件,有:

如果對乙個不可變物件複製,copy是指標複製,即淺拷貝;而mutablecopy則是物件複製,即深拷貝。(示例1)

如果是對可變物件複製,都是深拷貝,但copy複製返回的物件是不可變的。

深拷貝和淺拷貝

淺拷貝就是物件的資料成員之間的簡單賦值,如你設計了乙個沒有類而沒有提供它的複製建構函式,當用該類的乙個物件去給令乙個物件賦值時所執行的過程就是淺拷貝,如 class a a private int data int main 這一句b a 就是淺拷貝,執行完這句後b.data 5 如果物件中沒有其他...

淺拷貝和深拷貝

以下情況都會呼叫拷貝建構函式 乙個物件以值傳遞的方式傳入函式體 例如 已知class a,class b void func a a void func a a func b b 此時函式對b的操作是呼叫拷貝建構函式後的臨時拷貝物件。多數傳指標 乙個物件以值傳遞的方式從函式返回 如 return b...

深拷貝和淺拷貝

ios提供了copy和mutablecopy方法,顧名思義,copy就是複製了乙個imutable的物件,而mutablecopy就是複製了乙個mutable的物件。以下將舉幾個例子來說明。1 系統的非容器類物件 這裡指的是nsstring nsnumber等等一類的物件。nsstring stri...