美文网首页ios&&OC
iOS 浅拷贝 深拷贝

iOS 浅拷贝 深拷贝

作者: kindom_0129 | 来源:发表于2019-08-29 15:31 被阅读0次

    概念


    • 浅拷贝:指针拷贝,复制一个新的指针,指向同一块内存区域。即复制的对象和原对象都指向同一个内存


      浅拷贝
    • 深拷贝:内容拷贝,拷贝数据到一块新内存区域,指针指向新拷贝的内存。


      深拷贝.png
    • 非容器不可变对象/可变对象:NSString/ NSMutableString等

    • 容器不可变对象/可变对象:NSArray/NSMutableArray等

    先说说Strong修饰的变量


    @interface Copy()
    @property (nonatomic,strong)NSMutableString *strongStringA;
    @property (nonatomic,strong)NSMutableString *strongStringB;
    
    @end
    
    @implementation Copy
    
    -(void)strongStringCopy{
        NSMutableString *string = [NSMutableString stringWithFormat:@"name"];
        NSLog(@"原始NSMutableString的地址:%p",string);
        self.strongStringA=string;
        NSLog(@"对strongStringA赋值后的地址:%p",self.strongStringA);
        [string appendString:@" is kindom_0129"];
        NSLog(@"原始值修改后的地址:%p 值:%@",string,string);
        NSLog(@"对原始值修改后strongStringA的地址:%p 值:%@",self.strongStringA,self.strongStringA);
    }
    
    
    @end
    

    打印结果:

    原始NSMutableString的地址:0x6000018a57d0
    对strongStringA赋值后的地址:0x6000018a57d0
    原始值修改后的地址:0x6000018a57d0 值:name is kindom_0129
    对原始值修改后strongStringA的地址:0x6000018a57d0 值:name is kindom_0129

    • 结论:
      A使用属性对可变字符串做出了appendstring这样的操作,B中的值也会发生修改。
      strong: 为浅拷贝,也就是指针引用

    非容器不可变对象NSString


        NSString *string = [NSString stringWithFormat:@"name"];
        NSLog(@"原始string的地址:%p",string);
        NSString *copyString = [string copy];
        NSLog(@"拷贝string的地址:%p",copyString);
        NSMutableString *copyStringB = [string mutableCopy];
        NSLog(@"深拷贝string的地址:%p",copyStringB);
        [copyStringB appendString:@"id kindom_0129"];
        NSLog(@"深拷贝string的值:%@",copyStringB);
    

    打印结果:
    原始string的地址:0xe44d9dca7936d694
    拷贝string的地址:0xe44d9dca7936d694
    深拷贝string的地址:0x600003ed1260
    深拷贝string的值:nameid kindom_0129

    可以看出copy时对象的地址与原来的相同,而mutableCopy地址改变了,并且能够对其进行修改

    结论:
    1.对于非容器不可变对象的copy为浅拷贝,mutableCopy为深拷贝
    2.浅拷贝获得的对象地址和原对象地址一致, 返回的对象为不可变对象
    3.深拷贝返回新的内存地址,返回对象为可变对象

    非容器可变对象NSMutableString


    首先看下面这段代码:

    -(void)copyString{
        NSMutableString *string = [NSMutableString stringWithFormat:@"name"];
        NSLog(@"原始string的地址:%p",string);
        
        NSMutableString *copyString = [string copy];
        NSLog(@"拷贝string的地址:%p",copyString);
        
        [copyString appendString:@"test"];
    }
    

    结果呢?


    屏幕快照 2019-08-29 14.23.25.png

    看到了吗?居然crash了,为什么呢。我们细看下:
    我们的MutableString对象调用了copy之后,拷贝出来的字符串内存地址发生了变化,也就是说这里是发生了深拷贝。
    接着我们使用copyString调用appendString方法发生了很常规的闪退,日志显示我们拷贝出来的是NSTaggedPointerString,这是个不可变字符串。

    也就是说可变字符串在copy之后会发生深拷贝,拷贝出来的是一个不可变字符串!

    再来看看下面这段代码:

     -(void)copyString{
        NSMutableString *string = [NSMutableString stringWithFormat:@"name"];
        NSLog(@"原始string的地址:%p",string);
    
        NSMutableString *copyString = [string copy];
        NSLog(@"拷贝string的地址:%p",copyString);
        
        NSMutableString *copyStringB = [string mutableCopy];
        NSLog(@"深拷贝string的地址:%p",copyStringB);
        [copyStringB appendString:@"id kindom_0129"];
        NSLog(@"深拷贝string的值:%@",copyStringB);
    }
    

    结果:
    原始string的地址:0x60000140f9f0
    拷贝string的地址:0xd62b10f4fd1f50c5
    深拷贝string的地址:0x60000147a310
    深拷贝string的值:nameid kindom_0129

    结论:
    1.对于非容器可变对象的copy为深拷贝
    2.mutableCopy为深拷贝,并且可以修改
    3.可变字符串在copy之后会发生深拷贝,拷贝出来的是一个不可变字符串!

    容器不可变对象:NSArray等


    先来看看下面的代码:

    NSMutableString *str1 = [NSMutableString stringWithFormat:@"非容器可变对象"];
        
        NSArray *array = [NSArray arrayWithObjects:str1, @"非容器不可变对象", nil];
        NSArray *copyArray = [array copy];
        NSArray *mutableCopyArray = [array mutableCopy];
        
        NSLog(@"array_p: %p, class: %@", array, [array class]);
        NSLog(@"copyArray_p: %p, class: %@", copyArray, [copyArray class]);
        NSLog(@"mutableCopyArray_p: %p, class: %@", mutableCopyArray, [mutableCopyArray class]);
        
        NSLog(@"======原对象=====");
        NSLog(@"object_p: %p, class: %@", array[0], [array[0] class]);
        NSLog(@"object_p: %p, class: %@", array[1], [array[1] class]);
        
        NSLog(@"======copy对象=====");
        NSLog(@"object_p: %p, class: %@", copyArray[0], [copyArray[0] class]);
        NSLog(@"object_p: %p, class: %@", copyArray[1], [copyArray[1] class]);
        
        NSLog(@"======mutableCopy对象=====");
        NSLog(@"object_p: %p, class: %@", mutableCopyArray[0], [mutableCopyArray[0] class]);
        NSLog(@"object_p: %p, class: %@", mutableCopyArray[1], [mutableCopyArray[1] class]);
    

    结果:
    array_p: 0x6000005cca80, class: __NSArrayI
    copyArray_p: 0x6000005cca80, class: __NSArrayI
    mutableCopyArray_p: 0x600000bd03c0, class: __NSArrayM
    ======原对象=====
    object_p: 0x600000bd00c0, class: __NSCFString
    object_p: 0x10b5211e0, class: __NSCFConstantString
    ======copy对象=====
    object_p: 0x600000bd00c0, class: __NSCFString
    object_p: 0x10b5211e0, class: __NSCFConstantString
    ======mutableCopy对象=====
    object_p: 0x600000bd00c0, class: __NSCFString
    object_p: 0x10b5211e0, class: __NSCFConstantString

    结论:
    1.copy为浅拷贝;
    2.mutableCopy为深拷贝;
    3.无论是浅拷贝还是深拷贝,容器内的元素仍然是浅拷贝。

    容器可变对象:NSMutableArray等


    代码:

       NSMutableString *str1 = [NSMutableString stringWithFormat:@"非容器可变对象"];
        
        NSMutableArray *array = [NSMutableArray arrayWithObjects:str1, @"非容器不可变对象", nil];
        NSMutableArray *copyArray = [array copy];
        NSMutableArray *mutableCopyArray = [array mutableCopy];
        
        NSLog(@"array_p: %p, class: %@", array, [array class]);
        NSLog(@"copyArray_p: %p, class: %@", copyArray, [copyArray class]);
        NSLog(@"mutableCopyArray_p: %p, class: %@", mutableCopyArray, [mutableCopyArray class]);
        
        NSLog(@"======原对象=====");
        NSLog(@"object_p: %p, class: %@", array[0], [array[0] class]);
        NSLog(@"object_p: %p, class: %@", array[1], [array[1] class]);
        
        NSLog(@"======copy对象=====");
        NSLog(@"object_p: %p, class: %@", copyArray[0], [copyArray[0] class]);
        NSLog(@"object_p: %p, class: %@", copyArray[1], [copyArray[1] class]);
        
        NSLog(@"======mutableCopy对象=====");
        NSLog(@"object_p: %p, class: %@", mutableCopyArray[0], [mutableCopyArray[0] class]);
        NSLog(@"object_p: %p, class: %@", mutableCopyArray[1], [mutableCopyArray[1] class]);
    

    结果:
    array_p: 0x6000029f1c50, class: __NSArrayM
    copyArray_p: 0x6000027aab80, class: __NSArrayI
    mutableCopyArray_p: 0x6000029f19b0, class: __NSArrayM
    ======原对象=====
    object_p: 0x6000029f1b00, class: __NSCFString
    object_p: 0x10bdb11e0, class: __NSCFConstantString
    ======copy对象=====
    object_p: 0x6000029f1b00, class: __NSCFString
    object_p: 0x10bdb11e0, class: __NSCFConstantString
    ======mutableCopy对象=====
    object_p: 0x6000029f1b00, class: __NSCFString
    object_p: 0x10bdb11e0, class: __NSCFConstantString

    我们再添加一行代码:

    [copyArray addObject:@"dddd"];
    

    此时运行发现crash了:


    image.png

    结论:
    1.容器类可变对象mutableCopy和copy都返回一个新的容器,
    2.容器内的元素仍然是浅拷贝
    3.容器类可变对象copy后生成的新对象为不可变对象,这与非容器类可变对象copy后是一样的

    ***总结:


    1.copy并不一定是浅拷贝,如果被拷贝的对象是可变数组或者字符串,这时候会发生深拷贝,反之则是浅拷贝。
    2.copy出来的一定是不可变对象
    3.对于容器对象,无论是浅拷贝还是深拷贝,容器内的内容都是浅拷贝
    4.对于可变对象的深拷贝mutableCopy可以修改

    相关文章

      网友评论

        本文标题:iOS 浅拷贝 深拷贝

        本文链接:https://www.haomeiwen.com/subject/hggbectx.html