zoukankan      html  css  js  c++  java
  • 你真的了解iOS的深浅拷贝吗?

    最近在简书看到了一篇关于iOS深浅拷贝的博客,下面做一下学习总结:

    非集合类对象的copy和mutableCopy

    非集合类对象指NSString、NSNumber、NSMutableString等对象。对immutable(不可变对象)进行copy操作,就是简单的指针拷贝,进行mutableCopy操作时,是进行内容复制。对于mutable(可变对象)无论进行copy还是mutableCopy都是内容拷贝。

    // 非集合类对象的copy和mutablecopy
    // 1.不可变对象
    NSString *str = @"hello";
    NSString *str_copy = str.copy;
    NSMutableString *str_mutecopy = str.mutableCopy;
    [str_mutecopy appendString:@" world"];
    
    NSLog(@"%@---%p----%@",str,str,[str class]);
    NSLog(@"%@---%p----%@",str_copy,str_copy,[str_copy class]);
    NSLog(@"%@---%p----%@",str_mutecopy,str_mutecopy,[str_mutecopy class]);
    NSLog(@"
    ");
    
    // 输出
    // 2018-05-19 22:26:17.847234+0800 深浅拷贝练习[5861:566828] hello---0x100002060----__NSCFConstantString
    // 2018-05-19 22:26:17.847418+0800 深浅拷贝练习[5861:566828] hello---0x100002060----__NSCFConstantString
    // 2018-05-19 22:26:17.847475+0800 深浅拷贝练习[5861:566828] hello world---0x10053bab0----__NSCFString
    
    //2.可变对象
    NSMutableString *str_mute = [NSMutableString stringWithString:@"hello"];
    NSString *str_mute_copy = str_mute.copy;
    NSMutableString *str_mute_mutecopy = str_mute.mutableCopy;
    [str_mute appendString:@" world"];
    [str_mute_mutecopy appendString:@" Objective-C"];
    
    NSLog(@"%@---%p----%@",str_mute,str_mute,[str_mute class]);
    NSLog(@"%@---%p----%@",str_mute_copy,str_mute_copy,[str_mute_copy class]);
    NSLog(@"%@---%p----%@",str_mute_mutecopy,str_mute_mutecopy,[str_mute_mutecopy class]);
    
    // 输出
    // 2018-05-19 22:26:17.847544+0800 深浅拷贝练习[5861:566828] hello world---0x10053bc30----__NSCFString
    // 2018-05-19 22:26:17.847601+0800 深浅拷贝练习[5861:566828] hello---0x6f6c6c656855----NSTaggedPointerString
    // 2018-05-19 22:26:17.847619+0800 深浅拷贝练习[5861:566828] hello Objective-C---0x1005471d0----__NSCFString

    集合类对象的copy和mutableCopy

    集合类对象是指NSArray、NSDictionary等对象,对immutable对象进行copy,是指针拷贝,mutableCopy是进行内容拷贝。对mutable对象进行copy和mutableCopy时都是内容拷贝。但是集合对象的内容拷贝仅限于对象本身,对象元素仍然是指针拷贝。

    //集合类对象的copy和mutablecopy
    //1.不可变对象
    NSArray *arr = @[@"1",@"2",@"3"];
    NSArray *arr_copy = arr.copy;
    NSMutableArray *arr_mutecopy = arr.mutableCopy;
    [arr_mutecopy addObject:@"4"];
    
    NSLog(@"%@----%p----%@",arr,arr,[arr class]);
    NSLog(@"%@----%p----%@",arr_copy,arr_copy,[arr_copy class]);
    NSLog(@"%@----%p----%@",arr_mutecopy,arr_mutecopy,[arr_mutecopy class]);
    NSLog(@"
    ");
    
    // 输出
    // 2018-05-19 22:34:39.850322+0800 深浅拷贝练习[5927:578661] (
    //                                                     1,
    //                                                     2,
    //                                                     3
    //                                                     )----0x10070ae50----__NSArrayI
    // 2018-05-19 22:34:39.850423+0800 深浅拷贝练习[5927:578661] (
    //                                                     1,
    //                                                     2,
    //                                                     3
    //                                                     )----0x10070ae50----__NSArrayI
    // 2018-05-19 22:34:39.850488+0800 深浅拷贝练习[5927:578661] (
    //                                                     1,
    //                                                     2,
    //                                                     3,
    //                                                     4
    //                                                     )----0x10070b390----__NSArrayM


    //2.可变对象
    NSMutableArray *arr_mute = [NSMutableArray arrayWithObjects:@"1",@"2",@"3", nil];
    NSArray *arr_mute_copy = arr_mute.copy;
    NSMutableArray *arr_mute_mutecopy = arr_mute.mutableCopy;
    [arr_mute addObject:@"4"];
    [arr_mute_mutecopy addObject:@"5"];

    NSLog(@"%@----%p----%@",arr_mute,arr_mute,[arr_mute class]);
    NSLog(@"%@----%p----%@",arr_mute_copy,arr_mute_copy,[arr_mute_copy class]);
    NSLog(@"%@----%p----%@",arr_mute_mutecopy,arr_mute_mutecopy,[arr_mute_mutecopy class]);

    // 输出
    // 2018-05-19 22:34:39.850556+0800 深浅拷贝练习[5927:578661] (
    //                                                     1,
    //                                                     2,
    //                                                     3,
    //                                                     4
    //                                                     )----0x1031061e0----__NSArrayM
    // 2018-05-19 22:34:39.850571+0800 深浅拷贝练习[5927:578661] (
    //                                                     1,
    //                                                     2,
    //                                                     3
    //                                                     )----0x1031030a0----__NSArrayI
    // 2018-05-19 22:34:39.850601+0800 深浅拷贝练习[5927:578661] (
    //                                                     1,
    //                                                     2,
    //                                                     3,
    //                                                     5
    //                                                     )----0x103105910----__NSArray

    注意:集合类深拷贝和非集合类的深拷贝还是不太一样的,当我们对集合类进行mutableCopy操作时,虽然内存地址改变了,但是数组元素内存地址并没有发生改变,这是一个特例,也就是并不是真正意义上的完全深拷贝,也就是单层深拷贝。

    深拷贝(单层深拷贝)和完全拷贝

    深拷贝就是把原来对象的内容直接克隆一份到新对象里,但是这里有一个坑就是,他只会复制一层,不会复制更深层次的对象,例如:

    NSArray *arr = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"one"],@"two",@"three",@"four", nil];
    NSMutableString *str = arr[0];
    [str appendString:@"- add some data"];
    NSArray *arr_copy = arr.copy;
    NSMutableArray *arr_mutecopy = arr.mutableCopy;
    
    NSLog(@"%@----%p----%@----%p",arr,arr,[arr class],arr[0]);
    NSLog(@"%@----%p----%@----%p",arr_copy,arr_copy,[arr_copy class],arr_copy[0]);
    NSLog(@"%@----%p----%@----%p",arr_mutecopy,arr_mutecopy,[arr_mutecopy class],arr_mutecopy[0]);
    
    // 输出
    // 2018-05-19 22:57:09.819322+0800 深浅拷贝练习[6068:602956] (
    //                                                     "one- add some data",
    //                                                     two,
    //                                                     three,
    //                                                     four
    //                                                     )----0x100504fb0----__NSArrayI----0x10042aaa0
    // 2018-05-19 22:57:09.819514+0800 深浅拷贝练习[6068:602956] (
    //                                                     "one- add some data",
    //                                                     two,
    //                                                     three,
    //                                                     four
    //                                                     )----0x100504fb0----__NSArrayI----0x10042aaa0
    // 2018-05-19 22:57:09.819569+0800 深浅拷贝练习[6068:602956] (
    //                                                     "one- add some data",
    //                                                     two,
    //                                                    three,
    //                                                     four
    //                                                     )----0x100506a20----__NSArrayM----0x10042aaa0

    由此可知,arr_copy和arr_mutecopy对arr进行了内容拷贝,但是arr的可变字符串却没有进行内容拷贝,而是进行了单纯的浅拷贝(指针拷贝),那么arr、arr_copy和arr_mutecopy元素中第一个元素字符串是共享的,由此可以看出深拷贝并不是真正意义的完全拷贝,只是单层深拷贝。

    解决办法:

    归档和接档

    NSArray *arr = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"one"],@"two",@"three",@"four", nil];
    
    //归档和接档的方法解决
    NSMutableArray *arr_arc = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:arr]];
    
    NSMutableString *str = arr[0];
    [str appendString:@"- add some data"];
    NSArray *arr_copy = arr.copy;
    NSMutableArray *arr_mutecopy = arr.mutableCopy;
    
    NSLog(@"%@----%p----%@----%p",arr,arr,[arr class],arr[0]);
    NSLog(@"%@----%p----%@----%p",arr_copy,arr_copy,[arr_copy class],arr_copy[0]);
    NSLog(@"%@----%p----%@----%p",arr_mutecopy,arr_mutecopy,[arr_mutecopy class],arr_mutecopy[0]);
    NSLog(@"%@----%p----%@----%p",arr_arc,arr_arc,[arr_arc class],arr_arc[0]);
    
    // 输出
    // 2018-05-19 22:57:09.819322+0800 深浅拷贝练习[6068:602956] (
    //                                                     "one- add some data",
    //                                                     two,
    //                                                     three,
    //                                                     four
    //                                                     )----0x100504fb0----__NSArrayI----0x10042aaa0
    // 2018-05-19 22:57:09.819514+0800 深浅拷贝练习[6068:602956] (
    //                                                     "one- add some data",
    //                                                     two,
    //                                                     three,
    //                                                     four
    //                                                     )----0x100504fb0----__NSArrayI----0x10042aaa0
    // 2018-05-19 22:57:09.819569+0800 深浅拷贝练习[6068:602956] (
    //                                                     "one- add some data",
    //                                                     two,
    //                                                    three,
    //                                                     four
    //                                                     )----0x100506a20----__NSArrayM----0x10042aaa0
    // 2018-05-20 20:54:26.698263+0800 深浅拷贝练习[6506:682670] (
    //                                                     one,
    //                                                     two,
    //                                                     three,
    //                                                     four
    //                                                     )----0x100576610----__NSArrayI----0x100575e20
  • 相关阅读:
    Java线程池
    Servlet实现网页十天免登陆功能
    代码实现QQ消息轰炸
    数组模拟栈数据结构
    约瑟夫问题以及环形链表的解决方案
    ServletConfig中的方法
    Servlet的生命周期
    数组模拟环形队列
    数组模拟队列
    多线程实现奇偶数的依次输出
  • 原文地址:https://www.cnblogs.com/it-q/p/9064569.html
Copyright © 2011-2022 走看看