對(duì)深拷貝和淺拷貝的一些學(xué)習(xí)心得

摘要 : 文章參考http://www.cocoachina.com/ios/20160803/17275.html

一開始我一直以為拷貝方式只有兩種,并且對(duì)這兩種的拷貝方式也是分不清,然后就在網(wǎng)上學(xué)習(xí)了一下,寫一下自己的心得體會(huì),給大家分享一下.

首先 . OC對(duì)象的拷貝方式不是兩種而是三種.分別是

淺拷貝(shallow copy):在淺拷貝操作時(shí), 對(duì)于被復(fù)制的對(duì)象的每一層都是指針復(fù)制,并沒有對(duì)物理地址進(jìn)行復(fù)制,所以并不會(huì)重新開辟新的空間.

深復(fù)制(one-level-deep copy):在深復(fù)制操作的時(shí)候,是把對(duì)象的給復(fù)制過來,至少有一層是深復(fù)制.其實(shí)也不全是深復(fù)制,如果數(shù)據(jù)有很多層次,它就只復(fù)制了第一層,而第二層還是淺復(fù)制.

完全復(fù)制(real - deep copy):完全復(fù)制操作的時(shí)候,就是對(duì)于對(duì)象的每一層都進(jìn)行了復(fù)制,不僅物理地址復(fù)制,對(duì)象也復(fù)制.這才是真正的深拷貝.

圖片來源http://www.cocoachina.com/ios/20160803/17275.html

從圖片可以看出 ,我發(fā)現(xiàn)可變的對(duì)象 雖然只是用了copy ,但發(fā)現(xiàn)它并不是淺拷貝,而是深拷貝.但參數(shù)的類型竟然發(fā)生了改變,具體原因我也不清楚 ,如有大神 知道,可以幫小弟講解一下.


理解深復(fù)制(mutableCopy)

說多無益,代碼才是王道.

NSMutableArray *array = [NSMutableArray arrayWithObjects:

[NSMutableString stringWithString:@"a"],

[NSMutableString stringWithString:@"b"],

[NSMutableString stringWithString:@"c"],

[NSMutableString stringWithString:@"d"],

nil];

NSMutableArray *array1 = [NSMutableArray arrayWithObjects:

[NSMutableString stringWithString:@"A"],

[NSMutableString stringWithString:@"B"],

[NSMutableString stringWithString:@"C"],

[NSMutableString stringWithString:@"D"],

array, nil];

NSMutableArray *array2 ;

NSMutableString *str;

array2 = [array1 mutableCopy];

str = array1[4][1];

[str appendString:@"-----1"];

NSLog(@"array2------%@",array2);

NSLog(@"array1------%@",array1);

打印出來的結(jié)果卻讓人想不明白

2016-08-26 12:08:38.277 深淺拷貝[1117:64610] array2------(

A,

B,

C,

D,

(

a,

"b-----1",

c,

d

)

)

2016-08-26 12:08:38.278 深淺拷貝[1117:64610] array1------(

A,

B,

C,

D,

(

a,

"b-----1",

c,

d

)

)


試了一下又開了一下原文講的才知道,原來這就是深復(fù)制和完全復(fù)制的區(qū)別.

對(duì)于深復(fù)制,我一直認(rèn)為,深復(fù)制就是對(duì)于原有對(duì)象的內(nèi)容直接克隆過去,但代碼顯示的結(jié)果卻讓我產(chǎn)生疑惑,很是不明白,原來它只是復(fù)制一層對(duì)象,而不會(huì)復(fù)制第二層甚至更深層次的對(duì)象,其實(shí)對(duì)于這句話我是有疑問的,既然是復(fù)制了第一層,那么這第一層是說的A,B,C,D呢還是就是原本array1的層次,就是一個(gè)空的對(duì)象,但看代碼執(zhí)行的結(jié)果,我的想法應(yīng)該是對(duì)的,這個(gè)層次,對(duì)于我來說,好像并不是很清楚,同樣如果有大神知道,可以講解一下.

代碼array2 = [array1 mutableCopy]; 只是對(duì)數(shù)組array1 本身進(jìn)行內(nèi)容的拷貝.但里面的字符串對(duì)象沒有進(jìn)行內(nèi)容的拷貝,而是進(jìn)行的淺復(fù)制,只是指針的復(fù)制,對(duì)象還是公用的所以改變一個(gè)也會(huì)改變所有.

看來解決這個(gè)問題只能再看原文章了

換了復(fù)制方式的代碼 結(jié)果還是可人的.

array2 = [[NSMutableArray alloc]initWithArray:array1 copyItems:YES];

顯示結(jié)果是

2016-08-26 12:23:25.787 深淺拷貝[1195:69165] array2------(

A,

B,

C,

D,

(

a,

b,

c,

d

)

)

2016-08-26 12:23:25.787 深淺拷貝[1195:69165] array1------(

"A-----1",

B,

C,

D,

(

a,

b,

c,

d

)

)


發(fā)現(xiàn)沒有問題 但我總感覺 還是有問題,

str = array1[4][1];

方法一變發(fā)現(xiàn)打印的結(jié)果又和上面的一樣

2016-08-26 12:24:42.143 深淺拷貝[1218:70070] array2------(

A,

B,

C,

D,

(

a,

"b-----1",

c,

d

)

)

2016-08-26 12:24:42.144 深淺拷貝[1218:70070] array1------(

A,

B,

C,

D,

(

a,

"b-----1",

c,

d

)

)


唉, 還是失敗了,array2 = [[NSMutableArray alloc]initWithArray:array1 copyItems:YES];僅僅只是復(fù)制了一層,而下面的一層卻沒有復(fù)制.

看來我的試一下完全復(fù)制這個(gè)方法了.原來完全復(fù)制是歸檔和解檔啊.

array2 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array1]];

輸出的結(jié)果是

2016-08-26 12:30:12.292 深淺拷貝[1265:72371] array2------(

A,

B,

C,

D,

(

a,

b,

c,

d

)

)

2016-08-26 12:30:12.293 深淺拷貝[1265:72371] array1------(

A,

B,

C,

D,

(

a,

"b-----1",

c,

d

)

)

大功告成!!!!!

類的復(fù)制 就不在自己寫了 感覺并不是很難,就直接用原作者的.

類復(fù)制說完了對(duì)象的復(fù)制,我們來看看如何實(shí)現(xiàn)類的復(fù)制,因?yàn)楸容^簡(jiǎn)單,直接放上代碼定義類復(fù)制123456789101112131415#import@interface Person : NSObject@property(strong,nonatomic)NSString *age;

@property(strong,nonatomic)NSString *name;

@end

#import "Person.h"

@implementation Person

- (id)copyWithZone:(NSZone *)zone

{

Person *person = [[Person allocWithZone:zone] init];

person.age = self.age;

person.name = self.name;

return person;

}

@end

調(diào)用

Person *person = [[Person alloc]init];

person.age = @"dsdsd";

person.name = @"dsdsdddww";

Person *copyPerson = [person copy];?

NSLog(@"%@-----%@",copyPerson.age, copyPerson.name);可以看到copyPerson的兩個(gè)屬性和persona一樣。

@property中的copy關(guān)鍵字

在設(shè)置NSString類型的屬性的時(shí)候,我們最好設(shè)置為copy類型,這樣別人使用我們定義的屬性的時(shí)候,他不管怎么改動(dòng)該屬性的賦值,都不會(huì)影響我們給該屬性賦的值,為什么呢?

下面我們來看看

如上圖所示,string2的屬性是copy類型,可以看到是無法被修改的。

因?yàn)榇藭r(shí)string2和copystring的內(nèi)存地址不一樣,修改一個(gè),不會(huì)影響另外一個(gè)。

上圖所示,如果string2的屬性是strong類型,就可以被修改,如下圖所示:因?yàn)榇藭r(shí)string2和copystring的內(nèi)存地址都是一樣的,修改一個(gè),兩個(gè)就同時(shí)被修改copy關(guān)鍵字的NSMutableString崩潰


原因:copy關(guān)鍵字的string的setter方法實(shí)際上是把參數(shù)copy之后再賦值給變量_string,那么此時(shí)變量_string雖然被申明為NSMutableString,但是copy之后,就把變量_string變成了不可變的NSString類型,所以就會(huì)出現(xiàn)方法報(bào)錯(cuò),提示對(duì)不可變的NSString使用了NSMutableString的方法appendString。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容