Objective-C 之深拷貝和淺拷貝

3月箴言git

人的思想是了不得的,只要專一於某一項事業,就必定會作出使本身感到吃驚的成績來。—— 馬克·吐溫github

一、iOS中關於深拷貝和淺拷貝的概念數組

淺拷貝:淺拷貝並不拷貝對象自己,只是對指向對象的指針進行拷貝
深拷貝:直接拷貝對象到內存中一塊區域,而後把新對象的指針指向這塊內存app

在iOS中並非全部對象都支持Copy和MutableCopy,遵循NSCopying協議的類能夠發送Copy協議,遵循NSMutableCopying協議的類能夠發送MutableCopy消息。若是一個對象沒有遵循這兩個協議而發送Copy或者MutableCopy消息那麼會發生異常。若是要遵循NSCopying協議,那麼必須實現copyWithZone方法。若是要遵循NSMutableCopying協議那麼必須實現mutableCopyWithZone方法。ide

二、可變對象和不可變對象調用深拷貝和淺拷貝方法的區別以及具體示例:spa

2.1非容器類不可變對象3d

- (void)immutableStrCopyAndMutCopy
{
    NSString *immutableStr = @"不可變字符串";
    NSMutableString *immutableStrCopy = [immutableStr copy];
    NSMutableString *immutableStrMutCopy = [immutableStr mutableCopy];
    //    [immutableStrCopy appendString:@"22"];
    [immutableStrMutCopy appendString:@"33"];
    NSLog(@"immutableStrMutCopy = %@",immutableStrMutCopy);
    /*
     immutableStr_p = 0x107a58068 immutableStr = __NSCFConstantString
     immutableStrCopy_p = 0x107a58068 immutableStrCopy = __NSCFConstantString,
     immutableStrMutCopy_p = 0x6000034e07e0,immutableStrMutCopy= __NSCFString
     __NSCFConstantString 表示對象存儲在常量區,__NSCFString表示對象存儲在堆上
     */
    NSLog(@"\n immutableStr_p = %p immutableStr = %@ \n immutableStrCopy_p = %p immutableStrCopy = %@,\n immutableStrMutCopy_p = %p,immutableStrMutCopy= %@",immutableStr,[immutableStr class],immutableStrCopy,[immutableStrCopy class],immutableStrMutCopy,[immutableStrMutCopy class]);

}
非容器類不可變對象 執行copy 和 mutbleCopy

結論:指針

對非容器類的不可變對象 執行copy 是淺拷貝,地址相同,返回的也是不可變對象
                                  執行mutableCopy 是深拷貝,地址不一樣,返回的是可變對象code

2.2非容器類可變對象orm

- (void)mutableStrCopyAndMutCopy
{
    NSMutableString *mutableStr = [NSMutableString stringWithFormat:@"可變字符串"];
    
    NSMutableString *mutableStrCopy = [mutableStr copy];
    //copy 以後 變爲不可變對象,不可執行拼接操做,窒息該操做,直接崩潰!!
    //    [mutableStrCopy appendString:@"copy 以後拼接"];
    NSMutableString *mutableStrMutCopy = [mutableStr mutableCopy];
    [mutableStrMutCopy appendString:@"mutcopy"];
    /*
     mutableStr.p = 0x600001589230 mutableStr.class = __NSCFString mutableStr = 可變字符串
     mutableStrCopy.p = 0x6000015890b0 mutableStrCopy.class = __NSCFString,mutableStrCopy = 可變字符串
     mutableStrMutCopy.p = 0x6000015887b0,mutableStrMutCopy.class= __NSCFString,mutableStrMutCopy = 可變字符串mutcopy
     */
    NSLog(@"\n mutableStr.p = %p mutableStr.class = %@ mutableStr = %@ \n mutableStrCopy.p = %p mutableStrCopy.class = %@,mutableStrCopy = %@\n mutableStrMutCopy.p = %p,mutableStrMutCopy.class= %@,mutableStrMutCopy = %@",mutableStr,[mutableStr class],mutableStr,mutableStrCopy,[mutableStrCopy class],mutableStrCopy,mutableStrMutCopy,[mutableStrMutCopy class],mutableStrMutCopy);
    
}
非容器類可變對象執行 copy 和 mutableCopy

結論:
對於非容器類的可變對象 執行 copy 深拷貝,地址不一樣,返回的是不可變對象
                                  執行mutableCopy,深拷貝,地址不一樣,返回的是可變對象

2.3容器類不可變對象

- (void)imArrayCopyAndMutCopy
{
    NSString *immutableStr = @"不可變對象";
    NSMutableString *mutableStr = [NSMutableString stringWithFormat:@"可變對象兮"];
    NSArray *imArray = [NSArray arrayWithObjects:immutableStr,mutableStr, nil];
    NSArray *imArrayCopy = [imArray copy];
    NSArray *imArrayMutCopy = [imArray mutableCopy];
    /*
     imArray.p = 0x60000259d960 imArray.class = __NSArrayI
     imArrayCopy.p = 0x60000259d960 imArrayCopy.class = __NSArrayI
     imArrayMutCopy.p = 0x600002b839f0,imArrayMutCopy.class= __NSArrayM
     2019-03-03 12:13:35.401764+0800 MyNewTestDemo[13557:3186194] imArray ---tempStr.p = 0x1098d4088,tempStr = __NSCFConstantString,tempStr.class = 不可變對象
     2019-03-03 12:13:35.401864+0800 MyNewTestDemo[13557:3186194] imArray ---tempStr.p = 0x600002b83b70,tempStr = __NSCFString,tempStr.class = 可變對象兮
     2019-03-03 12:13:35.401945+0800 MyNewTestDemo[13557:3186194] imArrayCopy ---tempCopyStr.p = 0x1098d4088,tempCopyStr = __NSCFConstantString,tempCopyStr.class = 不可變對象
     2019-03-03 12:13:35.402043+0800 MyNewTestDemo[13557:3186194] imArrayCopy ---tempCopyStr.p = 0x600002b83b70,tempCopyStr = __NSCFString,tempCopyStr.class = 可變對象兮
     2019-03-03 12:13:35.402111+0800 MyNewTestDemo[13557:3186194] imArrayMutCopy ---tempMutCopyStr.p = 0x1098d4088,tempMutCopyStr = __NSCFConstantString,tempMutCopyStr.class = 不可變對象
     2019-03-03 12:13:35.402171+0800 MyNewTestDemo[13557:3186194] imArrayMutCopy ---tempMutCopyStr.p = 0x600002b83b70,tempMutCopyStr = __NSCFString,tempMutCopyStr.class = 可變對象兮
     */
    NSLog(@"\n imArray.p = %p imArray.class = %@  \n imArrayCopy.p = %p imArrayCopy.class = %@\n imArrayMutCopy.p = %p,imArrayMutCopy.class= %@",imArray,[imArray class],imArrayCopy,[imArrayCopy class],imArrayMutCopy,[imArrayMutCopy class]);
    
    for (id tempStr in imArray) {
        NSLog(@"imArray ---tempStr.p = %p,tempStr = %@,tempStr.class = %@\n",tempStr,[tempStr class],tempStr);
    }
    for (id tempCopyStr in imArrayCopy) {
        NSLog(@"imArrayCopy ---tempCopyStr.p = %p,tempCopyStr = %@,tempCopyStr.class = %@\n",tempCopyStr,[tempCopyStr class],tempCopyStr);
    }
    
    for (id tempMutCopyStr in imArrayMutCopy) {
        NSLog(@"imArrayMutCopy ---tempMutCopyStr.p = %p,tempMutCopyStr = %@,tempMutCopyStr.class = %@\n",tempMutCopyStr,[tempMutCopyStr class],tempMutCopyStr);
    }
    
}
容器類對象 copy或mutableCopy (本方法是針對數組)

結論:對於容器類的不可變對象 執行copy 對於容器來講是淺copy,地址相同,且返回的是不可變對象
                                           執行mutableCopy 對於容器來講是深拷貝,地址不一樣,且返回的是可變對象。
                                           對於容器內的對象(可變或不可變對象)而言,不管容器執行的是copy仍是mutableCopy,這些對象執行的都是淺拷貝

2.4容器類可變對象

- (void)mutArrayCopyAndMutCopy
{
    NSString *immutableStr = @"不可變對象";
    NSMutableString *mutableStr = [NSMutableString stringWithFormat:@"可變對象兮"];
    NSMutableArray *mutArray = [NSMutableArray arrayWithObjects:immutableStr,mutableStr, nil];
    
    /*
     mutArray.p = 0x600002c17000 mutArray.class = __NSArrayM
     mutArray.copy.p = 0x60000221ace0 mutArray.copy.Class = __NSArrayI
     mutArray.mutCopy.p = 0x600002c16fd0,mutArray.mutCopy.p= __NSArrayM
     2019-03-03 12:24:00.751299+0800 MyNewTestDemo[13742:3202669] mutArray ---tempStr.p = 0x10ec73088,tempStr = __NSCFConstantString,tempStr.class = 不可變對象
     2019-03-03 12:24:00.751410+0800 MyNewTestDemo[13742:3202669] mutArray ---tempStr.p = 0x600002c17330,tempStr = __NSCFString,tempStr.class = 可變對象兮
     2019-03-03 12:24:00.751502+0800 MyNewTestDemo[13742:3202669] mutArray.copy ---tempCopyStr.p = 0x10ec73088,tempCopyStr = __NSCFConstantString,tempCopyStr.class = 不可變對象
     2019-03-03 12:24:00.751594+0800 MyNewTestDemo[13742:3202669] mutArray.copy ---tempCopyStr.p = 0x600002c17330,tempCopyStr = __NSCFString,tempCopyStr.class = 可變對象兮
     2019-03-03 12:24:00.751694+0800 MyNewTestDemo[13742:3202669] mutArray.mutCopy ---tempMutCopyStr.p = 0x10ec73088,tempMutCopyStr = __NSCFConstantString,tempMutCopyStr.class = 不可變對象
     2019-03-03 12:24:00.751789+0800 MyNewTestDemo[13742:3202669] mutArray.mutCopy ---tempMutCopyStr.p = 0x600002c17330,tempMutCopyStr = __NSCFString,tempMutCopyStr.class = 可變對象兮
     */
    NSLog(@"\n mutArray.p = %p mutArray.class = %@  \n mutArray.copy.p = %p mutArray.copy.Class = %@\n mutArray.mutCopy.p = %p,mutArray.mutCopy.p= %@",mutArray,[mutArray class],[mutArray copy],[[mutArray copy] class],[mutArray mutableCopy],[[mutArray mutableCopy] class]);
    for (id tempStr in mutArray) {
        NSLog(@"mutArray ---tempStr.p = %p,tempStr = %@,tempStr.class = %@\n",tempStr,[tempStr class],tempStr);
    }
    for (id tempCopyStr in [mutArray copy]) {
        NSLog(@"mutArray.copy ---tempCopyStr.p = %p,tempCopyStr = %@,tempCopyStr.class = %@\n",tempCopyStr,[tempCopyStr class],tempCopyStr);
    }
    
    for (id tempMutCopyStr in [mutArray mutableCopy]) {
        NSLog(@"mutArray.mutCopy ---tempMutCopyStr.p = %p,tempMutCopyStr = %@,tempMutCopyStr.class = %@\n",tempMutCopyStr,[tempMutCopyStr class],tempMutCopyStr);
    }
}
容器類可變對象 copy和mutableCopy (本方法是針對數組)

結論:對於容器類可變對象 執行copy,深拷貝,地址不一樣,返回的是不可變對象
                                     執行mutableCopy,深拷貝,地址不一樣,返回的是不可變對象
                                     容器內的對象(不管可變或不可變),均爲淺拷貝(地址相同)

- (void)imDicCopyAndMutCopy
{
    NSString *immutableStrOne = @"不可變對象1";
    NSMutableString *mutableStrOne = [NSMutableString stringWithFormat:@"可變對象1"];
    NSString *immutableStrTwo = @"不可變對象2";
    NSMutableString *mutableStrTwo = [NSMutableString stringWithFormat:@"可變對象2"];
    /*
     immutableDic.p = 0x6000003d2400 immutableDic.class = __NSDictionaryI
     immutableDic.copy.p = 0x6000003d2400 immutableDic.copy.class = __NSDictionaryI
     immutableDic.mutcopy.p = 0x600002dc8e00,immutableDic.mutcopy.class= __NSDictionaryM
     2019-03-03 12:37:08.098513+0800 MyNewTestDemo[13840:3214742] immutableDic ---key.p = 0x600002398e40,key.class = __NSCFString,key = 可變對象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可變對象1
     2019-03-03 12:37:08.098588+0800 MyNewTestDemo[13840:3214742] immutableDic ---key.p = 0x600002399260,key.class = __NSCFString,key = 可變對象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可變對象1
     2019-03-03 12:37:08.098698+0800 MyNewTestDemo[13840:3214742] immutableDic ---key.p = 0x105a20148,key.class = __NSCFConstantString,key = 不可變對象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可變對象1
     2019-03-03 12:37:08.098785+0800 MyNewTestDemo[13840:3214742] immutableDic ---key.p = 0x105a20188,key.class = __NSCFConstantString,key = 不可變對象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可變對象1
     2019-03-03 12:37:08.098873+0800 MyNewTestDemo[13840:3214742] immutableDic.copy ---key.p = 0x600002398e40,key.class = __NSCFString,key = 可變對象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可變對象1
     2019-03-03 12:37:08.098950+0800 MyNewTestDemo[13840:3214742] immutableDic.copy ---key.p = 0x600002399260,key.class = __NSCFString,key = 可變對象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可變對象1
     2019-03-03 12:37:08.099037+0800 MyNewTestDemo[13840:3214742] immutableDic.copy ---key.p = 0x105a20148,key.class = __NSCFConstantString,key = 不可變對象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可變對象1
     2019-03-03 12:37:08.099140+0800 MyNewTestDemo[13840:3214742] immutableDic.copy ---key.p = 0x105a20188,key.class = __NSCFConstantString,key = 不可變對象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可變對象1
     2019-03-03 12:37:08.160496+0800 MyNewTestDemo[13840:3214742] immutableDic.mutcopy ---key.p = 0x105a20188,key.class = __NSCFConstantString,key = 不可變對象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可變對象1
     2019-03-03 12:37:08.160610+0800 MyNewTestDemo[13840:3214742] immutableDic.mutcopy ---key.p = 0x600002399260,key.class = __NSCFString,key = 可變對象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可變對象1
     2019-03-03 12:37:08.160716+0800 MyNewTestDemo[13840:3214742] immutableDic.mutcopy ---key.p = 0x105a20148,key.class = __NSCFConstantString,key = 不可變對象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可變對象1
     2019-03-03 12:37:08.160811+0800 MyNewTestDemo[13840:3214742] immutableDic.mutcopy ---key.p = 0x600002398e40,key.class = __NSCFString,key = 可變對象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可變對象1
     
     */
    NSDictionary *immutableDic = @{immutableStrOne:immutableStrOne,immutableStrTwo:mutableStrOne,mutableStrOne:immutableStrOne,mutableStrTwo:mutableStrOne};
    
    NSLog(@"\n immutableDic.p = %p immutableDic.class = %@  \n immutableDic.copy.p = %p immutableDic.copy.class = %@\n immutableDic.mutcopy.p = %p,immutableDic.mutcopy.class= %@",immutableDic,[immutableDic class],[immutableDic copy],[[immutableDic copy] class],[immutableDic mutableCopy],[[immutableDic mutableCopy] class]);
    
    [immutableDic enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) {
        NSLog(@"immutableDic ---key.p = %p,key.class = %@,key = %@ ,obj.p = %p,obj.class = %@,obj = %@ \n",key,[key class],key,obj,[obj class],obj);
        
    }];
    
    [[immutableDic copy] enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) {
        NSLog(@"immutableDic.copy ---key.p = %p,key.class = %@,key = %@ ,obj.p = %p,obj.class = %@,obj = %@ \n",key,[key class],key,obj,[obj class],obj);
    }];
    
    
    [[immutableDic mutableCopy] enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) {
        NSLog(@"immutableDic.mutcopy ---key.p = %p,key.class = %@,key = %@ ,obj.p = %p,obj.class = %@,obj = %@ \n",key,[key class],key,obj,[obj class],obj);
        
    }];

}
容器類對象 針對字典驗證

     結論:容器類不可變對象  字典和數組的結論是一致的,且對於字典中的key或value ,都是淺拷貝

能夠簡單整理爲:不可變對象的copy,都是淺拷貝,地址相同,
                        可變對象的copy和mutablecopy,都是深拷貝,
                        copy方法返回的是不可變對象,mutableCopy返回的是可變對象,

                        容器對象內的對象始終是淺拷貝。

代碼可點擊github,項目內搜索關鍵字copy and mutableCopy

相關文章
相關標籤/搜索