本文邏輯圖
copy和mutableCopy賦值的異同
1.copy贮匕,mutableCopy都是深拷貝姐仅,也就是會重新開辟出一塊內(nèi)存來保存和原有值相同的值,原有值的變化不會修改被賦值對象的值刻盐。
2.copy的被賦值對象不可被修改掏膏,mutableCopy得到的對象可被修改。且不受原值和接受值的類型影響敦锌。
3.容器對象(數(shù)組)中的元素是淺拷貝馒疹,修改后依舊會對被賦值對象造成影響。
下面我們依次通過非容器變量和容器變量來驗證上面三條乙墙。
1.copy颖变,mutableCopy都是深拷貝,也就是會重新開辟出一塊內(nèi)存來保存和原有值相同的值听想,原有值的變化不會修改被賦值對象的值
初始化一個mStrOrigin腥刹,通過copy方法賦值給mStrFromCopy,mStrFromMCopy,輸出三者的值和地址哗魂。觀察他們的值和地址是否相同肛走,從而判斷是copy和mutableCopy是否深拷貝。
NSMutableString *mStrOrigin = [[NSMutableString alloc] initWithString:@"mStr"];
NSMutableString *mStrFromCopy = [mStrOrigin copy];
NSMutableString *mStrFromMCopy = [mStrOrigin mutableCopy];
NSLog(@"值:mStrOrigin:%@ mStrFromCopy:%@ mStrFromMCopy:%@ \n 地址:mStrOrigin:%p mStrFromCopy:%p mStrFromMCopy:%p \n",mStrOrigin,mStrFromCopy,mStrFromMCopy,mStrOrigin,mStrFromCopy,mStrFromMCopy);
有輸出
值:mStrOrigin:mStr mStrFromCopy:mStr mStrFromMCopy:mStr
地址:mStrOrigin:0x7fec40c5bd00 mStrFromCopy:0xa0000007274536d4 mStrFromMCopy:0x7fec40c59c00
現(xiàn)象:mStrOrigin录别,mStrFromCopy朽色,mStrFromMCopy三者地址都不一樣
結(jié)論:copy和mutableCopy是深拷貝
我們修改原值mStrOrigin 觀察mStrFromCopy,mStrFromMCopy是否會隨之變化
[mStrOrigin appendString:@"-change1"];
NSLog(@"值:mStrOrigin:%@ mStrFromCopy:%@ mStrFromMCopy:%@ \n 地址:mStrOrigin:%p mStrFromCopy:%p mStrFromMCopy:%p \n",mStrOrigin,mStrFromCopy,mStrFromMCopy,mStrOrigin,mStrFromCopy,mStrFromMCopy);
有輸出
值:mStrOrigin:mStr-change1 mStrFromCopy:mStr mStrFromMCopy:mStr
地址:mStrOrigin:0x7fec40c5bd00 mStrFromCopy:0xa0000007274536d4 mStrFromMCopy:0x7fec40c59c00
現(xiàn)象:隨著mStrOrigin變化,mStrFromMCopy和mStrFromMCopy均沒有隨之變化
結(jié)論:copy和mutableCopy出來的是新的內(nèi)存组题,原值改變新的值不改變葫男。
他們的賦值結(jié)構(gòu)圖如下:
2.copy的被賦值對象不可被修改崔列,mutableCopy得到的對象可被修改梢褐。且不受原值和接受值的類型影響旺遮。
嘗試修改mStrFromCopy(由copy方法得到),查看是否會崩潰盈咳,從而判斷copy出來的對象不可被修改的
NSMutableArray *mArrOrigin = [[NSMutableArray alloc] init];
NSMutableString *mstr1 = [[NSMutableString alloc] initWithString:@"value1"];
NSMutableString *mstr2 = [[NSMutableString alloc] initWithString:@"value2"];
NSMutableString *mStrOrigin = [[NSMutableString alloc] initWithString:@"mStr"];
[mArrOrigin addObject:mstr1];
[mArrOrigin addObject:mstr2];
NSMutableArray *mArrFromCopy = [mArrOrigin copy];
NSMutableString *mStrFromCopy = [mStrOrigin copy];
[mStrFromCopy appendString:@"-change3"]; //崩潰 'Attempt to mutate immutable object with appendString:'
[mArrFromMCopy addObject:mstr3];
現(xiàn)象:數(shù)組和字符串操作均發(fā)生崩潰
結(jié)論:copy出來的內(nèi)存是不可被修改的耿眉,就算你使用可變變量指針去接受,也不能被修改
嘗試修改mStrFromMCopy和mArrFromCopy(由mutablecopy得到)鱼响,查看是否會奔潰
NSMutableString *mStrFromMCopy = [mStrOrigin mutableCopy];
NSMutableArray *mArrFromMCopy = [mArrOrigin mutableCopy];
[mStrFromMCopy appendString:@"-change4"];
[mArrFromMCopy addObject:mstr3];
NSLog(@"%@ %@",mStrFromMCopy,mArrFromMCopy);
現(xiàn)象:修改成功
結(jié)論:mutableCopy出來的數(shù)據(jù)地址可被修改
既然可以修改鸣剪,如果我們用不可變量指針接受mutableCopy值,那內(nèi)存地址還能修改嗎丈积?
我們試驗下筐骇,此處用可變變量mStrFromMCopy2弱引用指向mutableCopy的數(shù)據(jù)地址江滨,嘗試修改mStrFromMCopy2并輸出三者 查看是否能修改成功。
NSString *strFromMCopy = [mStrOrigin mutableCopy];
NSMutableString *mStrFromMCopy2 = strFromMCopy;
//輸出地址告唆,證明此時mStrFromMCopy2和strFromMCopy指向同一個數(shù)據(jù)內(nèi)存地址
NSLog(@"值:strFromMCopy:%@ mStrFromMCopy2:%@ 地址:strFromMCopy:%p mStrFromMCopy2:%p",strFromMCopy,mStrFromMCopy2,strFromMCopy,mStrFromMCopy2);
[mStrFromMCopy2 appendString:@"-change5"];
NSLog(@"值:strFromMCopy:%@ mStrFromMCopy2:%@ 地址:strFromMCopy:%p mStrFromMCopy2:%p",strFromMCopy,mStrFromMCopy2,strFromMCopy,mStrFromMCopy2);
現(xiàn)象:修改mStrFromMCopy2成功
結(jié)論:mutableCopy出來的數(shù)據(jù)地址可被修改间雀,就算接受指針是不可變類型。此處還說明一個問題茄螃,即指針可以指向不同類型的數(shù)據(jù)內(nèi)存
剛才試驗發(fā)現(xiàn)【原值是可變對象连锯,用不可變類型的指針去獲取mutableCopy得到的值,發(fā)現(xiàn)數(shù)據(jù)地址可被修改】
那如果原值本身就不可修改拼弃,那mutableCopy后的被賦值對象是否也可修改摇展。
//創(chuàng)建不可變對象
NSString *strOrigin = [[NSString alloc] initWithUTF8String:"string 1"];
mStrFromMCopy = [strOrigin mutableCopy];
[mStrFromMCopy appendString:@"-change6"];
NSLog(@"值:strOrigin %@,mStrFromMCopy %@",strOrigin,mStrFromMCopy);
輸出
值:strOrigin string 1盯孙,mStrFromMCopy string 1-change6
現(xiàn)象:修改mStrFromMCopy成功
結(jié)論:mutableCopy出來的數(shù)據(jù)地址可被修改振惰,就算原值是不可變類型
3.容器變量中元素均是淺拷貝
創(chuàng)建一個可變?nèi)萜鱩ArrOrigin垄懂,初始化添加value1痛垛,value2兩個元素匙头。并通過copy和mutableCopy賦值給mArrFromCopy乾胶,mArrFromMCopy朽寞。為原值增加一個元素value3脑融,輸出三者地址和值缩宜。查看地址和值觀察是否是深拷貝
NSMutableArray *mArrOrigin = [[NSMutableArray alloc] init];
NSMutableString *mstr1 = [[NSMutableString alloc] initWithString:@"value1"];
NSMutableString *mstr2 = [[NSMutableString alloc] initWithString:@"value2"];
NSMutableString *mstr3 = [[NSMutableString alloc] initWithString:@"value3"];
[mArrOrigin addObject:mstr1];
[mArrOrigin addObject:mstr2];
NSMutableArray *mArrFromCopy = [mArrOrigin copy];
NSMutableArray *mArrFromMCopy = [mArrOrigin mutableCopy];
[mArrOrigin addObject:mstr3];
NSLog(@"值:mArrOrigin :%@ mArrFromCopy:%@ mArrFromMCopy%@\n 地址:mArrOrigin :%p\n mArrFromCopy:%p\n mArrFromMCopy:%p\n",mArrOrigin,mArrFromCopy,mArrFromMCopy,mArrOrigin,mArrFromCopy,mArrFromMCopy);
輸出:
值:
mArrOrigin :(
value1,
value2,
value3
) mArrFromCopy:(
value1,
value2
) mArrFromMCopy(
value1,
value2
)
地址:
mArrOrigin :0x7fe102d0e380
mArrFromCopy:0x7fe102d26070
mArrFromMCopy:0x7fe102d26090
現(xiàn)象:mArrFromCopy锻煌,mArrFromMCopy出來的容器本身是新的地址宋梧。(不可變?nèi)萜魍?br> 結(jié)論:copy和mutableCopy出來的是新的地址,原容器改變释涛,新容器不改變倦沧。賦值結(jié)構(gòu)圖如下
容器本身不變展融,那么里面的元素呢?
我們修改原來容器中元素的值mstr1扑浸,輸出三個容器暂雹,觀察他們的值是否會改變,從而來判斷容器對象的copy和mutableCopy賦值是否元素也會深拷貝
[mstr1 appendString:@"-change2"];
NSLog(@"值:mArrOrigin :%@ mArrFromCopy:%@ mArrFromMCopy%@\n 地址:mArrOrigin :%p\n mArrFromCopy:%p\n mArrFromMCopy:%p\n",mArrOrigin,mArrFromCopy,mArrFromMCopy,mArrOrigin,mArrFromCopy,mArrFromMCopy);
輸出
值:
mArrOrigin :(
"value1-change2",
value2,
value3
) mArrFromCopy:(
"value1-change2",
value2
) mArrFromMCopy(
"value1-change2",
value2
)
地址:
mArrOrigin :0x7fe102d0e380
mArrFromCopy:0x7fe102d26070
mArrFromMCopy:0x7fe102d26090
現(xiàn)象:mArrFromCopy仙逻,mArrFromMCopy的元素隨之改變
結(jié)論:容器的copy和mutableCopy賦值中,容器本身是深拷貝檬贰,容器中的元素依舊是淺拷貝
結(jié)構(gòu)示意圖如下:
綜上所述:
1.copy和mutableCopy都是深拷貝
2.copy和mutableCopy生成的內(nèi)存地址上的數(shù)據(jù)是否可變跟原值類型和被賦值的指針類型無關(guān)翁涤。
如不可變數(shù)據(jù)copy出來的內(nèi)存萌踱,用可變指針指向,當(dāng)你嘗試修改的時候鸳粉,仍然會發(fā)生崩潰届谈。提示不可修改
3.容器對象本身遵循上面規(guī)則弯汰,容器中的元素依舊是淺拷貝(即多個指針指向一個數(shù)據(jù)地址)
項目地址https://github.com/ai966669/lbCopyAndMutableCopy
交流qq:578172874
錯誤之處希望能幫忙提出來,一起學(xué)習(xí),O(∩_∩)O謝謝了