美文网首页
深拷贝与浅拷贝区别

深拷贝与浅拷贝区别

作者: boboliu123 | 来源:发表于2018-06-26 15:44 被阅读0次

    浅拷贝:浅拷贝是指针拷贝,对一个实现NSCopying协议的对象进行浅拷贝,会创建一个新的指针来指向原始对象。两个指针指向同一个内存区域,如果原始对象的内容发生改变,新的对象同样会发生改变;新的对象内容变化,原始对象内容也会发生变化。如图所示:


    image.png

    深拷贝:深拷贝是内容拷贝,他会把原始对象的内容复制出来,然后让这个内容放到新的对象里面。两个指针指向不同的内存区域,原始对象的内容变化不影响新的对象;新的对象内容变化也不影响原始对象。


    image.png

    验证上述深拷贝和浅拷贝的代码:

        //深拷贝示例:
        //str内容改变的时候,strCopy内容并没有发生变化
        NSMutableString *str = [NSMutableString stringWithFormat:@"123"];
        NSString *strCopy = [str copy];
        NSLog(@"str:%@, strCopy:%@", str, strCopy);
        [str appendFormat:@"123"];
        NSLog(@"str:%@, strCopy:%@", str, strCopy);
    2018-06-26 15:10:21.825600+0800 CopyTest[14774:1661930] str:123, strCopy:123
    2018-06-26 15:10:21.825816+0800 CopyTest[14774:1661930] str:123123, strCopy:123
    
        //想要使用copy方法的条件:必须遵守<NSCopying>协议,实现 copyWithZone: 方法
        NSMutableArray *muArr = [NSMutableArray array];
        NSArray *arr = [NSArray array];
        
        NSString *str = [NSString string];
        NSMutableString *muStr = [NSMutableString string];
        
        NSDictionary *dic = [NSDictionary dictionary];
        NSMutableDictionary *muDic = [NSMutableDictionary dictionary];
        
        //拷贝出来对象的类型
        //数组
        NSLog(@"%@", [arr.copy class]);
        NSLog(@"%@", [arr.mutableCopy class]);
        NSLog(@"%@", [muArr.copy class]);
        NSLog(@"%@", [muArr.mutableCopy class]);
        
        //字符串
        NSLog(@"%@", [str.copy class]);
        NSLog(@"%@", [str.mutableCopy class]);
        NSLog(@"%@", [muStr.copy class]);
        NSLog(@"%@", [muStr.mutableCopy class]);
        
        //字典
        NSLog(@"%@", [dic.copy class]);
        NSLog(@"%@", [dic.mutableCopy class]);
        NSLog(@"%@", [muDic.copy class]);
        NSLog(@"%@", [muDic.mutableCopy class]);
        
        //拷贝出来对象的内存地址比较
        //数组
        NSLog(@"数组:%p, %p", arr, arr.copy); //浅拷贝
        NSLog(@"数组:%p, %p", arr, arr.mutableCopy); //深拷贝
        NSLog(@"数组:%p, %p", muArr, muArr.copy); //深拷贝
        NSLog(@"数组:%p, %p", muArr, muArr.mutableCopy); //深拷贝
        
        
        //字符串
        NSLog(@"字符串:%p, %p", str, str.copy); //浅拷贝
        NSLog(@"字符串:%p, %p", str, str.mutableCopy); //深拷贝
        NSLog(@"字符串:%p, %p", muStr, muStr.copy); //深拷贝
        NSLog(@"字符串:%p, %p", muStr, muStr.mutableCopy); //深拷贝
        
        //字典
        NSLog(@"字典:%p, %p", dic, dic.copy); //浅拷贝
        NSLog(@"字典:%p, %p", dic, dic.mutableCopy); //深拷贝
        NSLog(@"字典:%p, %p", muDic, muDic.copy); //深拷贝
        NSLog(@"字典:%p, %p", muDic, muDic.mutableCopy); //深拷贝
    2018-06-26 14:51:41.168790+0800 CopyTest[14400:1606517] __NSArray0
    2018-06-26 14:51:41.168990+0800 CopyTest[14400:1606517] __NSArrayM
    2018-06-26 14:51:41.169081+0800 CopyTest[14400:1606517] __NSArray0
    2018-06-26 14:51:41.169164+0800 CopyTest[14400:1606517] __NSArrayM
    2018-06-26 14:51:41.169285+0800 CopyTest[14400:1606517] __NSCFConstantString
    2018-06-26 14:51:41.169516+0800 CopyTest[14400:1606517] __NSCFString
    2018-06-26 14:51:41.169615+0800 CopyTest[14400:1606517] __NSCFConstantString
    2018-06-26 14:51:41.169731+0800 CopyTest[14400:1606517] __NSCFString
    2018-06-26 14:51:41.169834+0800 CopyTest[14400:1606517] __NSDictionary0
    2018-06-26 14:51:41.169940+0800 CopyTest[14400:1606517] __NSDictionaryM
    2018-06-26 14:51:41.170034+0800 CopyTest[14400:1606517] __NSFrozenDictionaryM
    2018-06-26 14:51:41.170149+0800 CopyTest[14400:1606517] __NSDictionaryM
    2018-06-26 14:51:41.170261+0800 CopyTest[14400:1606517] 数组:0x60400001e0a0, 0x60400001e0a0
    2018-06-26 14:51:41.170340+0800 CopyTest[14400:1606517] 数组:0x60400001e0a0, 0x604000049270
    2018-06-26 14:51:41.170457+0800 CopyTest[14400:1606517] 数组:0x6040000587b0, 0x60400001e0a0
    2018-06-26 14:51:41.170564+0800 CopyTest[14400:1606517] 数组:0x6040000587b0, 0x60000044e430
    2018-06-26 14:51:41.170790+0800 CopyTest[14400:1606517] 字符串:0x10075c320, 0x10075c320
    2018-06-26 14:51:41.170963+0800 CopyTest[14400:1606517] 字符串:0x10075c320, 0x60000044e430
    2018-06-26 14:51:41.171171+0800 CopyTest[14400:1606517] 字符串:0x604000058d20, 0x101666030
    2018-06-26 14:51:41.171391+0800 CopyTest[14400:1606517] 字符串:0x604000058d20, 0x604000049270
    2018-06-26 14:51:41.171873+0800 CopyTest[14400:1606517] 字典:0x60400001e090, 0x60400001e090
    2018-06-26 14:51:41.172208+0800 CopyTest[14400:1606517] 字典:0x60400001e090, 0x604000425140
    2018-06-26 14:51:41.172415+0800 CopyTest[14400:1606517] 字典:0x60400003dc20, 0x604000425140
    2018-06-26 14:51:41.172520+0800 CopyTest[14400:1606517] 字典:0x60400003dc20, 0x604000425140
    
    根据上面代码输出内容可以总结出如下结论:copy拷贝出来的对象类型总是不可变类型 image.png image.png

    延伸:在写代码的时候碰到一个有趣的现象,深拷贝改变了原始数据内容,新的内容依然改变。

        NSMutableArray *arr = [NSMutableArray array];
        NSMutableArray *subArr = [NSMutableArray array];
        [subArr addObject:@"1"];
        [arr addObject:subArr];
        NSMutableArray *muArr = [arr mutableCopy]; //深拷贝
        NSLog(@"arr:%@, muArr:%@", arr, muArr);
        [subArr addObject:@"2"];
        NSLog(@"arr:%@, muArr:%@", arr, muArr);
    2018-06-26 15:36:05.813570+0800 CopyTest[15167:1736602] arr:(
            (
            1
        )
    ), muArr:(
            (
            1
        )
    )
    2018-06-26 15:36:05.813769+0800 CopyTest[15167:1736602] arr:(
            (
            1,
            2
        )
    ), muArr:(
            (
            1,
            2
        )
    )
    

    猜测:这里的数组相当于一个容器里面套了一个容器。深拷贝的限制只是针对外层的容器而言的,对里面的容器并没有限制。
    我们通过代码来验证一下:

        NSMutableArray *arr = [NSMutableArray array];
        NSMutableArray *subArr = [NSMutableArray array];
        [subArr addObject:@"1"];
        [arr addObject:subArr];
        NSMutableArray *muArr = [arr mutableCopy]; //深拷贝
        NSLog(@"arr:%@, muArr:%@", arr, muArr);
        [muArr addObject:@"2"];
        NSLog(@"arr:%@, muArr:%@", arr, muArr);
    2018-06-26 15:42:04.404419+0800 CopyTest[15287:1755382] arr:(
            (
            1
        )
    ), muArr:(
            (
            1
        )
    )
    2018-06-26 15:42:04.404628+0800 CopyTest[15287:1755382] arr:(
            (
            1
        )
    ), muArr:(
            (
            1
        ),
        2
    )
    

    我们给拷贝出来的新数组外层添加一个数据@“2”,运行出来的结果跟我们预测一样,只是新数组发生了变化。原始数组的数据依然不变。这里可以看做不完全深拷贝,我们平常使用的一般都是不完全深拷贝。想要实现完全深拷贝需要重写copyWithZone:方法来实现。

    相关文章

      网友评论

          本文标题:深拷贝与浅拷贝区别

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