上篇文章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,这样在开发中很容易会用到。尤其是在数据源比较复杂,且不可以更改数据源的情况下。

相关资料

assign/retain/copy及深浅拷贝的区别

深拷贝和完全拷贝对比的探究相关推荐

  1. 浅拷贝、深拷贝、值拷贝和位拷贝

    首先: 位拷贝就是浅拷贝,值拷贝就是深拷贝. 编译器会在必要的时候,自己产生默认的拷贝构造函数和赋值函数,采用的位拷贝. 自己可以重新定义 拷贝构造函数,要注意采用值拷贝. Q:什么是浅拷贝(shal ...

  2. B18_NumPy副本和视图(视图或浅拷贝、副本或深拷贝、深浅拷贝)

    NumPy副本和视图 副本是一个数据的完整的拷贝,如果我们对副本进行修改,它不会影响到原始数据,物理内存不在同一位置. 视图是数据的一个别称或引用,通过该别称或引用亦便可访问.操作原有数据,但原有数据 ...

  3. C++ 类的深拷贝与浅拷贝||深拷贝通过重载拷贝构造函数与重载赋值运算符实现

    http://blog.csdn.net/wangshihui512/article/details/9842225 在面向对象程序设计中,对象间的相互拷贝和赋值是经常进行的操作. 如果对象在申明的同 ...

  4. 深拷贝——将对象拷贝到底

    假设我们有一个这样的需求,我们需要编辑修改一份表单,修改后提交之前想还原到之前的表单的值,这样我们就需要对原始表单有一个备份 // 原始表单 var form = {name: '张三',age: 1 ...

  5. C++浅拷贝(值拷贝)和深拷贝(位拷贝)

    参考网址:https://www.cnblogs.com/BlueTzar/articles/1223313.html https://www.cnblogs.com/xiaodingmu/p/740 ...

  6. 关于浅拷贝、深拷贝的探究

    浅拷贝.深拷贝.完全拷贝 在这里介绍三个概念: 浅拷贝:在拷贝操作时,对于被拷贝的对象的每一层拷贝都是指针拷贝. 深拷贝:在拷贝操作时,对于被拷贝的对象至少有一层拷贝是对象拷贝. 完全拷贝:在拷贝操作 ...

  7. assign/retain/copy各内存管理特性的差异

    MRC下各内存管理特性 assign特性 当数据类型为int.float等原生类型时,可以使用assign,否则可能导致内存泄露.例如当使用malloc分配了一块内存,并把它的地址赋值给了指针a,后来 ...

  8. .NET 6 数组拷贝性能对比

    本文来对比多个不同的方法进行数组拷贝,和测试其性能 测试性能必须采用基准(标准)性能测试方法,否则测试结果不可信.在 dotnet 里面,可以采用 BenchmarkDotNet 进行性能测试.详细请 ...

  9. java拷贝函数_Java的深拷贝与浅拷贝的几种实现方式

    1.介绍 关于Java的深拷贝和浅拷贝,简单来说就是创建一个和已知对象一模一样的对象.可能日常编码过程中用的不多,但是这是一个面试经常会问的问题,而且了解深拷贝和浅拷贝的原理,对于Java中的所谓值传 ...

最新文章

  1. linux swp 内存不足,Linux 增加 Swap 交换分区解决内存不足
  2. linux复盘:构架搭建lamp(安装)
  3. iOS APP上架被拒重新提交审核教程
  4. 简单使用JDOM解析XML
  5. Xcode 4.4 的新特性 | LLVM 4.0 的新语法
  6. 全球计算机科学硕士申请,2019爱尔兰留学都柏林大学计算机科学硕士申请
  7. java数据结构源码_java 数据结构. 源代码阅读
  8. 《Elasticsearch 源码解析与优化实战》第18章:写入速度优化
  9. 计算机专业可以当警校吗,警校开设的计算机类专业,毕业生就业方向偏向于信息安全,请注意...
  10. 戴尔通过F12一次性引导菜单刷新BIOS
  11. opencv图片保存0字节_openCV将8bit(1像素对应8bit)图像保存为1bit(1像素对应1bit)...
  12. ChatGPT大规模封号...
  13. 传说中的BNET边缘传输
  14. 神经网络正向与反向传播
  15. 计算机领域英文单词怎么读
  16. 打开APPStore跳转到指定APP
  17. 单考单招计算机试卷及答案,高职单考单招计算机模拟试卷一模板.doc
  18. CCF中国开源大会开源雨林论坛丨七大亮点议题抢鲜看!
  19. vs中c语言图形显示出来,VS2010+Opencv+MFC读取图像和视频显示在Picture控件
  20. php.ini sum

热门文章

  1. 微前端在平台级管理系统中的最佳实践
  2. 计算机弹音乐百度百科,音乐术语
  3. 微信3d小游戏(three)-逻辑设计与场景添加
  4. 如何用大数据进行甜品店选址要素分析
  5. js根据文字(保存大小,字体)计算文字长度,并根据容器显示省略号
  6. 有时感觉自己很是虚伪
  7. python ogr_Python+OGR库学习(三):将含有字段值的TXT文件写入shpfile
  8. 控制互联网就是控制世界
  9. java ftp 被动模式_ftp 主动模式与被动模式
  10. 有控制雷电武器的java游戏_雷电飞机射击游戏 JAVA