一、深拷貝和淺拷貝####
- 深拷貝:對(duì)象拷貝 - 直接拷貝內(nèi)容。
- 單層深拷貝:這種方式只能夠提供一層內(nèi)存拷貝(one-level-deep copy),并非真正的深拷貝。
- 淺拷貝:指針拷貝 - 將指針中的地址值拷貝一份。
二、對(duì)于非集合對(duì)象 Copy 與 mutableCopy 的實(shí)踐#####
- 思路:我用四個(gè)方案來(lái)驗(yàn)證 Copy 與 mutableCopy 的區(qū)別。
- 方案:
- 方案一:
copy不可變的字符串
- 方案一:
NSString*str = @"aaa";
NSString*copyStr = [str copy];
NSLog(@"str = %p copyStr= %p",str,copyStr);
NSLog(@"指針地址:str = %p copyStr= %p",&str,©Str);
輸出結(jié)果:str = 0x104d94068
copyStr= 0x104d94068
指針地址:str = 0x7fff529e9aa8
copyStr= 0x7fff529e9aa0
小結(jié):對(duì)不可變的字符串的copy
,我們對(duì)象的內(nèi)存地址沒(méi)有改變,只是指針的地址改變了,所以在這里我們默認(rèn)進(jìn)行了一次淺拷貝
,只拷貝了指針。
- 方案二:`copy可變的字符串`
NSMutableString*str1 = [NSMutableString stringWithFormat:@"bbb"];
NSString*copyStr1 = [str1 copy];
NSLog(@"str1 = %p copyStr1 = %p",str1,copyStr1);
NSLog(@"str1 = %p copyStr1= %p",&str1,©Str1);
輸出結(jié)果:str1 = 0x7fa522712cd0
copyStr1 = 0x7fa522717ba0
指針地址:str1 = 0x7fff529e9a98
copyStr1= 0x7fff529e9a90
小結(jié):對(duì)可變字符串的copy,我們默認(rèn)進(jìn)行了一次深拷貝,直接拷貝了對(duì)象。
- 方案三:mutableCopy不可變字符串的
NSString*str2 = @"ccc";
NSMutableString *copyStr2 = [str2 mutableCopy];
NSLog(@"str2 = %p copyStr2 = %p",str2,copyStr2);
輸出結(jié)果:str2 = 0x10d216108
copyStr2 = 0x7fa522726290
小結(jié):對(duì)于不可變字符串的mutableCopy我們默認(rèn)進(jìn)行了深拷貝。
- 方案四:mutableCopy可變字符串
NSMutableString*str3 = [NSMutableString stringWithFormat:@"ddd"];
NSMutableString*copyStr3 = [str3 mutableCopy];
NSLog(@"str3 = %p copyStr3 = %p",str3,copyStr3);
輸出結(jié)果:str3 = 0x7fa5227153c0
copyStr3 = 0x7fa5227263f0
小結(jié):對(duì)于可變字符串的mutableCopy我們默認(rèn)進(jìn)行了深拷貝。
三、對(duì)于集合對(duì)象采用 Copy 和 MutableCopy 的實(shí)踐
- 對(duì)集合對(duì)象采用 Copy 和 mutableCopy 來(lái)進(jìn)行實(shí)踐
NSArray * arr = @[@"1",@"2",@"3"];
NSMutableArray * mutableArr = [arr mutableCopy];
NSArray * copyArr = [arr copy];
NSMutableArray * newArr = [NSMutableArray arrayWithObjects:@"3",@"2",@"1", nil];
NSArray * newCopyArr = [newArr copy];
NSMutableArray * newMutableCopyArr = [newArr mutableCopy];
//測(cè)試 arr 的 copy 和 mutableCopy
NSString * str = [arr firstObject];
NSString * copyStr = [copyArr firstObject];
NSString * mutableStr = [mutableArr firstObject];
//測(cè)試 mutableArr 的 copy 和 mutableCopy
NSString * str = [newArr firstObject];
NSString * newCopyStr = [newCopyArr firstObject];
NSString * newMutableCopyStr = [newMutableCopyArr firstObject];
圖3-1.png
圖 3-2.png
圖3-3.png
- 通過(guò)圖 3-1 可以見(jiàn)到,對(duì)于不可變的 arr 如果進(jìn)行 copy 的話會(huì)進(jìn)行淺拷貝,如果 mutableCopy 會(huì)進(jìn)行內(nèi)容拷貝。但是,通過(guò)圖 3-2 打印出的地址信息,這里的內(nèi)容拷貝僅僅是拷貝 array 這個(gè)對(duì)象,array 集合內(nèi)的元素仍然是指針拷貝。所以可以定義為是單層深拷貝。
- 通過(guò)圖 3-3 可以看出,對(duì)于可變的集合元素的 copy 與 mutableCopy 都是單層深復(fù)制。
四、結(jié)論####
- 對(duì)于非集合對(duì)象
- copy:
因?yàn)閏opy默認(rèn)返回的是不可變的,所以當(dāng)我們對(duì)一個(gè)不可變的字符串進(jìn)行copy的時(shí)候,我們只是拷貝了它的指針(淺拷貝)。當(dāng)我們對(duì)一個(gè)可變的字符串進(jìn)行拷貝的時(shí)候,因?yàn)轭愋娃D(zhuǎn)變了,我們需對(duì)其進(jìn)行深拷貝
。 - mutableCopy:默認(rèn)返回的是一個(gè)可變的對(duì)象,適用于可變的對(duì)象,例如NSMutableString,NSMutableArray,NSMutableDictionary、etc。
無(wú)論對(duì)于可變的字符串還是不可變的字符串進(jìn)行mutableCopy,系統(tǒng)都默認(rèn)進(jìn)行深拷貝
,那么為什么對(duì)于相同類型的進(jìn)行mutableCopy返回的仍然是新的對(duì)象呢,因?yàn)樵谶@里系統(tǒng)要保證,舊的對(duì)象和新的對(duì)象都是可變的,切他們之前不會(huì)相互影響。
- copy:
- 對(duì)于集合對(duì)象
- 對(duì)于不可變的集合對(duì)象,copy 是淺拷貝,mutableCopy 是單層深拷貝。
- 對(duì)于可變的集合對(duì)象,無(wú)論 copy 或者 mutableCopy 都是單層深拷貝。