深拷贝和完全拷贝对比的探究
上篇文章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及深浅拷贝的区别
深拷贝和完全拷贝对比的探究相关推荐
- 浅拷贝、深拷贝、值拷贝和位拷贝
首先: 位拷贝就是浅拷贝,值拷贝就是深拷贝. 编译器会在必要的时候,自己产生默认的拷贝构造函数和赋值函数,采用的位拷贝. 自己可以重新定义 拷贝构造函数,要注意采用值拷贝. Q:什么是浅拷贝(shal ...
- B18_NumPy副本和视图(视图或浅拷贝、副本或深拷贝、深浅拷贝)
NumPy副本和视图 副本是一个数据的完整的拷贝,如果我们对副本进行修改,它不会影响到原始数据,物理内存不在同一位置. 视图是数据的一个别称或引用,通过该别称或引用亦便可访问.操作原有数据,但原有数据 ...
- C++ 类的深拷贝与浅拷贝||深拷贝通过重载拷贝构造函数与重载赋值运算符实现
http://blog.csdn.net/wangshihui512/article/details/9842225 在面向对象程序设计中,对象间的相互拷贝和赋值是经常进行的操作. 如果对象在申明的同 ...
- 深拷贝——将对象拷贝到底
假设我们有一个这样的需求,我们需要编辑修改一份表单,修改后提交之前想还原到之前的表单的值,这样我们就需要对原始表单有一个备份 // 原始表单 var form = {name: '张三',age: 1 ...
- C++浅拷贝(值拷贝)和深拷贝(位拷贝)
参考网址:https://www.cnblogs.com/BlueTzar/articles/1223313.html https://www.cnblogs.com/xiaodingmu/p/740 ...
- 关于浅拷贝、深拷贝的探究
浅拷贝.深拷贝.完全拷贝 在这里介绍三个概念: 浅拷贝:在拷贝操作时,对于被拷贝的对象的每一层拷贝都是指针拷贝. 深拷贝:在拷贝操作时,对于被拷贝的对象至少有一层拷贝是对象拷贝. 完全拷贝:在拷贝操作 ...
- assign/retain/copy各内存管理特性的差异
MRC下各内存管理特性 assign特性 当数据类型为int.float等原生类型时,可以使用assign,否则可能导致内存泄露.例如当使用malloc分配了一块内存,并把它的地址赋值给了指针a,后来 ...
- .NET 6 数组拷贝性能对比
本文来对比多个不同的方法进行数组拷贝,和测试其性能 测试性能必须采用基准(标准)性能测试方法,否则测试结果不可信.在 dotnet 里面,可以采用 BenchmarkDotNet 进行性能测试.详细请 ...
- java拷贝函数_Java的深拷贝与浅拷贝的几种实现方式
1.介绍 关于Java的深拷贝和浅拷贝,简单来说就是创建一个和已知对象一模一样的对象.可能日常编码过程中用的不多,但是这是一个面试经常会问的问题,而且了解深拷贝和浅拷贝的原理,对于Java中的所谓值传 ...
最新文章
- linux swp 内存不足,Linux 增加 Swap 交换分区解决内存不足
- linux复盘:构架搭建lamp(安装)
- iOS APP上架被拒重新提交审核教程
- 简单使用JDOM解析XML
- Xcode 4.4 的新特性 | LLVM 4.0 的新语法
- 全球计算机科学硕士申请,2019爱尔兰留学都柏林大学计算机科学硕士申请
- java数据结构源码_java 数据结构. 源代码阅读
- 《Elasticsearch 源码解析与优化实战》第18章:写入速度优化
- 计算机专业可以当警校吗,警校开设的计算机类专业,毕业生就业方向偏向于信息安全,请注意...
- 戴尔通过F12一次性引导菜单刷新BIOS
- opencv图片保存0字节_openCV将8bit(1像素对应8bit)图像保存为1bit(1像素对应1bit)...
- ChatGPT大规模封号...
- 传说中的BNET边缘传输
- 神经网络正向与反向传播
- 计算机领域英文单词怎么读
- 打开APPStore跳转到指定APP
- 单考单招计算机试卷及答案,高职单考单招计算机模拟试卷一模板.doc
- CCF中国开源大会开源雨林论坛丨七大亮点议题抢鲜看!
- vs中c语言图形显示出来,VS2010+Opencv+MFC读取图像和视频显示在Picture控件
- php.ini sum