74.深拷贝和完全拷贝对比的探究

来源:互联网 发布:淘宝搜索宝贝显示地址 编辑:程序博客网 时间:2024/05/01 08:53

上一篇文章assign/retain/copy及深浅拷贝的区别写到浅拷贝, 深拷贝, 以及完全拷贝, 包括由整理的 demo得出的一些结论。 今天就来就深拷贝和完全拷贝来做一些探究。

注意

这里集合类中的对象使用的是储存在堆区的对象, 不可以用常量区的对象, 否则会影响最终结果。

深拷贝数组

    NSString *elementOne = [NSString stringWithFormat:@"我屮艸芔茻"];    NSArray *array = [NSArray arrayWithObjects:elementOne, nil];    NSMutableArray *arr_mc = [array mutableCopy];    NSLog(@"array:  第一层 = %p, 第二层element = %p",array,array[0]);    NSLog(@"arr_mc: 第一层 = %p, 第二层element = %p",arr_mc,arr_mc[0]);

打印结果:

array: 第一层 = 0x7ff50bf16b60, 第二层element = 0x7ff50bf16b30
arr_mc: 第一层 = 0x7ff50bf51270, 第二层element = 0x7ff50bf16b30

总结:
根据打印结果可以发现, 深拷贝上面的数组时, 其中数组arr_mc 会另外开辟一个空间来存储, 但是其中的元素的地址却没有另外开辟一个空间来存储. 这个理解是不对的, 其实深拷贝时数组arr_mc 和其中的元素的地址确实改变了, 不要忘了数组arr_mc的地址就等于它首元素的地址(%p打印&array[0])。但是, 这个元素中存储的是一个指针,而且这个指针就是数组array中的elementOne的指针. 这就说明当进行 mutableCopy 时, 会将整个集合拷贝到一个新开辟的内存空间, 但是里面的内容或者说指针并没有改变, 而是一并拷贝过来.
所以就要有下面要说的完全拷贝, 顾名思义, 就是利用递归的原理, 将集合以及集合中所有层次的集合和对象进行 mutableCopy, 达到完全复制的效果.

完全拷贝分类添加

利用递归的原理, 将集合以及集合中所有层次的集合和对象进行 mutableCopy, 达到完全复制的效果.

//NSDictionary (DCCompleteCopy)- (NSMutableArray *)mutableDeepCopy{    NSUInteger count = [self count];    id cArray[count];    for (NSUInteger i = 0; i < count; i++) {        id obj = self[i];        if ([obj respondsToSelector:@selector(mutableDeepCopy)]) {            cArray[i] = [obj mutableDeepCopy];        } else if ([obj respondsToSelector:@selector(mutableCopyWithZone:)]) {            cArray[i] = [obj mutableCopy];        } else if ([obj respondsToSelector:@selector(deepCopy)]) {            cArray[i] = [obj deepCopy];        } else if ([obj respondsToSelector:@selector(copyWithZone:)]) {            cArray[i] = [obj copy];        } else {            //DLog(@"********Error:NSArray MutableDeepCopy Failed!!! ********");            return nil;        }    }    return [NSMutableArray arrayWithObjects:cArray count:count];}//NSDictionary (DCCompleteCopy)- (NSMutableDictionary *)mutableDeepCopy{    NSUInteger count = [self count];    id cObjects[count];    id cKeys[count];    NSEnumerator *e = [self keyEnumerator];    NSUInteger i = 0;    id thisKey;    while ((thisKey = [e nextObject]) != nil) {        id obj = self[thisKey];        if ([obj respondsToSelector:@selector(mutableDeepCopy)]) {            cObjects[i] = [obj mutableDeepCopy];        } else if ([obj respondsToSelector:@selector(mutableCopyWithZone:)]) {            cObjects[i] = [obj mutableCopy];        } else if ([obj respondsToSelector:@selector(deepCopy)]) {            cObjects[i] = [obj deepCopy];        } else if ([thisKey respondsToSelector:@selector(copyWithZone:)]) {            cObjects[i] = [thisKey copy];        } else {            //DLog(@"********Error:NSDictionary Key DeepCopy Failed!!! ********")            return nil;        }        if ([thisKey respondsToSelector:@selector(deepCopy)]) {            cKeys[i] = [thisKey deepCopy];        } else if ([thisKey respondsToSelector:@selector(copyWithZone:)]) {            cKeys[i] = [thisKey copy];        } else {            //DLog(@"********Error:NSDictionary Key DeepCopy Failed!!! ********")            return nil;        }        ++i;    }    return [NSMutableDictionary dictionaryWithObjects:cObjects forKeys:cKeys count:count];}

数组两层完全拷贝

NSString *elementOne = [NSString stringWithFormat:@"我屮艸芔茻"];    NSArray *array = [NSArray arrayWithObjects:elementOne, nil];    NSMutableArray *arr_mc = [array mutableCopy];    NSMutableArray *arr_mdc = [array mutableDeepCopy];    NSLog(@"array:  第一层 = %p, 第二层element = %p",array,array[0]);    NSLog(@"arr_mc: 第一层 = %p, 第二层element = %p",arr_mc,arr_mc[0]);    NSLog(@"arr_mdc:第一层 = %p, 第二层element = %p",arr_mdc,arr_mdc[0]);

打印结果:

array: 第一层 = 0x7fe488e12f90, 第二层element = 0x7fe488e16910
arr_mc: 第一层 = 0x7fe488e0a6b0, 第二层element = 0x7fe488e16910
arr_mdc:第一层 = 0x7fe488e0f880, 第二层element = 0x7fe488e12f50

数组三层完全拷贝

    NSString *elementOne = [NSString stringWithFormat:@"我屮艸芔茻"];    NSArray *arr_one = [NSArray arrayWithObjects:elementOne, nil];    NSArray *array = [NSArray arrayWithObjects:arr_one, nil];    NSMutableArray *arr_mc = [array mutableCopy];    NSMutableArray *arr_mdc = [array mutableDeepCopy];    NSLog(@"array:  第一层 = %p, 第二层 = %p, 第三层element = %p",array,array[0],array[0][0]);    NSLog(@"arr_mc: 第一层 = %p, 第二层 = %p, 第三层element = %p",arr_mc,arr_mc[0],arr_mc[0][0]);    NSLog(@"arr_mdc:第一层 = %p, 第二层 = %p, 第三层element = %p",arr_mdc,arr_mdc[0],arr_mdc[0][0]);

打印结果:

array: 第一层 = 0x7fe488e138e0, 第二层 = 0x7fe488e16df0, 第三层element = 0x7fe488e08f80
arr_mc: 第一层 = 0x7fe488e13900, 第二层 = 0x7fe488e16df0, 第三层element = 0x7fe488e08f80
arr_mdc:第一层 = 0x7fe488e16890, 第二层 = 0x7fe488e16860, 第三层element = 0x7fe488e138a0

字典两层完全拷贝

    NSString *elementOne = [NSString stringWithFormat:@"我屮艸芔茻"];    NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:elementOne, @"element", nil];    NSMutableDictionary *dic_mc = [dic mutableCopy];    NSMutableDictionary *dic_mdc = [dic mutableDeepCopy];    NSLog(@"dic:    第一层 = %p, 第二层element = %p",dic,dic[@"element"]);    NSLog(@"dic_mc: 第一层 = %p, 第二层element = %p",dic_mc,dic_mc[@"element"]);    NSLog(@"dic_mdc:第一层 = %p, 第二层element = %p",dic_mdc,dic_mdc[@"element"]);

打印结果:

dic: 第一层 = 0x7fe488c0a070, 第二层element = 0x7fe488c0d3c0
dic_mc: 第一层 = 0x7fe488c05370, 第二层element = 0x7fe488c0d3c0
dic_mdc:第一层 = 0x7fe488c24a10, 第二层element = 0x7fe488c1ed70

字典三层完全拷贝

NSString *elementOne = [NSString stringWithFormat:@"我屮艸芔茻"];    NSDictionary *dic_one = [NSDictionary dictionaryWithObjectsAndKeys:elementOne, @"element", nil];    NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:dic_one, @"one", nil];    NSMutableDictionary *dic_mc = [dic mutableCopy];    NSMutableDictionary *dic_mdc = [dic mutableDeepCopy];    NSLog(@"dic:    第一层 = %p, 第二层 = %p, 第三层element = %p",dic,dic[@"one"],dic[@"one"][@"element"]);    NSLog(@"dic_mc: 第一层 = %p, 第二层 = %p, 第三层element = %p",dic_mc,dic_mc[@"one"],dic_mc[@"one"][@"element"]);    NSLog(@"dic_mdc:第一层 = %p, 第二层 = %p, 第三层element = %p",dic_mdc,dic_mdc[@"one"],dic_mdc[@"one"][@"element"]);

打印结果:

dic: 第一层 = 0x7fe488e14c60, 第二层 = 0x7fe488e168c0, 第三层element = 0x7fe488e14c30
dic_mc: 第一层 = 0x7fe488e14ca0, 第二层 = 0x7fe488e168c0, 第三层element = 0x7fe488e14c30
dic_mdc:第一层 = 0x7fe488e14ec0, 第二层 = 0x7fe488e14e50, 第三层element = 0x7fe488e14dd0

数组字典混合三层完全拷贝

    NSString *elementOne = [NSString stringWithFormat:@"我屮艸芔茻"];    NSDictionary *dic_one = [NSDictionary dictionaryWithObjectsAndKeys:elementOne, @"element", nil];    NSArray *array = [NSArray arrayWithObjects:dic_one, nil];    NSMutableArray *arr_mc = [array mutableCopy];    NSMutableArray *arr_mdc = [array mutableDeepCopy];    NSLog(@"array->dic:  第一层 = %p, 第二层 = %p, 第三层element = %p",array,array[0],array[0][@"element"]);    NSLog(@"arr_mc->dic: 第一层 = %p, 第二层 = %p, 第三层element = %p",arr_mc,arr_mc[0],arr_mc[0][@"element"]);    NSLog(@"arr_mdc->dic:第一层 = %p, 第二层 = %p, 第三层element = %p",arr_mdc,arr_mdc[0],arr_mdc[0][@"element"]);

打印结果:

array->dic: 第一层 = 0x7fe488d086d0, 第二层 = 0x7fe488da0220, 第三层element = 0x7fe488da1a80
arr_mc->dic: 第一层 = 0x7fe488d94730, 第二层 = 0x7fe488da0220, 第三层element = 0x7fe488da1a80
arr_mdc->dic:第一层 = 0x7fe488d06e00, 第二层 = 0x7fe488d94170, 第三层element = 0x7fe488d14c70

总结

根据递归原理, 关于集合的每个层次都会遍历到, 而且其中的元素也都会遍历到, 也就是每个层次都进行了一个 mutableCopy , 这样在开发中很容易会用到. 尤其是在数据源比较复杂, 且不可以更改数据源的情况下.

0 0
原创粉丝点击