小议iOS中的浅复制和深复制

作者: ManoBoo | 来源:发表于2016-05-12 15:40 被阅读891次

前言:

提到iOS中的浅复制和深复制的区别,大家都知道浅复制过来的是对象的地址,而深复制,相当于重新开辟了内存空间,存储这个对象。


用代码说话

①单个对象的浅复制与深复制

/// 单个对象 浅复制、深赋值
- (void)ordinaryCopyVSMutableCopy {
    
    NSString *str = @"hehe";
    NSLog(@"源字符:%p",str);
    
    //浅
    NSString *cStr = [str copy];
    NSLog(@"浅复制: Cstr = %p",cStr);
    
    NSString *temp = [str copyWithZone:nil];
    NSLog(@"copyWithZone: temp = %p",temp);
    
    //深
    NSString *mStr = [str mutableCopy];
    NSLog(@"深复制: mStr = %p",mStr);
}

输出结果:

单个对象深浅复制输出结果.png
tips:可以看到 copycopyWithZone方法都是浅复制,对象的地址并没有改变,而mutableCopy重新开辟了内存控件,是深复制

数组及集合类对象的浅复制、深复制、完全复制

我们先定义一个原始数组

NSArray *originArr = [NSArray arrayWithObjects:@"1",@"2", nil];
NSLog(@"原数组 地址:%p",originArr);
NSLog(@"原数组中对象的地址: %p,%p \n",originArr[0],originArr[1]);

看代码:

①对数组进行浅复制
//对数组进行浅复制
  NSArray *copyArr = [originArr copy];
  NSLog(@"浅复制 地址:%p",copyArr);
  NSLog(@"浅复制数组中对象的地址: %p,%p \n",copyArr[0],copyArr[1]);

对比输出结果看:

数组浅复制结果对比.png
tips:可以看到 不论是数组本身还是数组中的元素,地址都没有发生变化,这就是完完全全的浅复制
那么问题1:[NSArray arrayWithArray:originArr] 是浅复制 还是 深复制呢
 NSArray *arr = [NSArray arrayWithArray:originArr];
 NSLog(@"arrayWithArray深复制 地址:%p",arr);
 NSLog(@"arrayWithArray深复制数组中对象的地址: %p,%p \n",arr[0],arr[1]);

结果:

arrayWithArray结果.png
tips:arr相比于源数组,算是一次深复制,但是数组中的元素地址依旧没有发生变化
②对数组进行深复制
 NSArray *mCopyArr = [originArr mutableCopy];
 NSLog(@"深复制 地址:%p",mCopyArr);
 NSLog(@"深复制数组中对象的地址: %p,%p \n",mCopyArr[0],mCopyArr[1]);

打印地址发现:

数组深复制.png ]
可以发现mCopyArr相比于原先的数组算是深复制了,但是内部的元素依旧是原先数组中的元素

问题2:[[NSArray alloc] initWithArray:.... copyItems:true] 是浅复制 还是 深复制呢

 NSArray *array = [[NSArray alloc] initWithObjects:[[NSMutableString alloc] initWithString:@"1"], @"2",nil];
 NSLog(@"array 地址: %p",array);
 NSLog(@"array中元素的地址 :%p,%p",array[0],array[1]);
    
 NSArray *arrWithCopyItem = [[NSArray alloc] initWithArray:array copyItems:true];
 NSLog(@"arrWithCopyItem深复制 地址:%p",arrWithCopyItem);
 NSLog(@"arrWithCopyItem深复制数组中对象的地址: %p,%p \n",arrWithCopyItem[0],arrWithCopyItem[1]);

输出结果:

copyItems深复制、浅复制测试.png
可以看到,arrWithCopyItem对于源数组array中的可变对象进行的是深复制,对不可变对象做的是浅复制,所以可以称,[[NSArray alloc] initWithArray:.... copyItems:true]方法是与源数组做了一次不完全的深复制,对于其中的不可变对象依旧是浅复制
tips:字典的[NSDictionary alloc] initWithDictionary:... copyItems:..这个方法结果同上

问题来了:这不算真正意义上的深复制,即完全复制,那用什么方法可以实现完全复制呢?

②对数组进行完全复制

方法有很多种,这里简单介绍两种:
一:归档、解挡操作

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:originArr];
NSData *aData = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSArray *mmCopyArr = (NSArray *)aData;
NSLog(@"①归档深复制 地址:%p",mmCopyArr);
NSLog(@"①归档深复制数组中对象的地址: %p,%p \n",mmCopyArr[0],mmCopyArr[1]);
源数组.png
归档、解档后.png

可以看到,不仅数组本身为深复制,数组中的元素也都重新开辟了内存空间

二:对数组进行遍历深复制,该方法较为简单,就不写代码了

Github项目地址

点击去我的Github下载Demo

相关文章

  • 小议iOS中的浅复制和深复制

    前言: 提到iOS中的浅复制和深复制的区别,大家都知道浅复制过来的是对象的地址,而深复制,相当于重新开辟了内存空间...

  • iOS

    开发记录 iOS 深复制与浅复制 浅拷贝就是拷贝后,并没有进行真正的复制,而是复制的对象和原对象都指向同一个地址 ...

  • python中的浅拷贝和深拷贝

    浅拷贝和深拷贝: 浅拷贝 shallow copy 浅拷贝是指在对象复制过程中,只复制一层变量,不会复...

  • 浅拷贝和深拷贝

    本文参考:JavaScript中的浅拷贝和深拷贝js 深拷贝 vs 浅拷贝深入剖析 JavaScript 的深复制...

  • 设计模式 - 原型模式

    注意深复制与浅赋值的问题 C#中如果需要实现深复制,必须实现 ICloneable 接口。

  • 深拷贝与浅拷贝的理解及常用方法

    深拷贝和浅拷贝的区别 首先深复制和浅复制只针对像 Object, Array 这样的复杂对象的。简单来说,浅复制只...

  • iOS 集合的深复制与浅复制

    iOS 集合的深复制与浅复制 概念 对象拷贝有两种方式:浅复制和深复制。顾名思义,浅复制,并不拷贝对象本身,仅仅是...

  • iOS 深、浅拷贝的理解

    iOS 的深、浅拷贝通过一张图片能够很直观理解: 对于系统的非容器类对象,对不可变对象复制,copy是指针复制(浅...

  • iOS全解11:特殊问题

    1、浅拷贝和深拷贝的区别? 浅拷贝:只复制指向对象的指针,指针指向同一个地址,而不复制引用对象本身。深拷贝:复制引...

  • js中对象的复制,浅复制(浅拷贝)和深复制(深拷贝)

    在js中,我们经常复制一个对象,复制数据,那么就会有人问了,怎么复制,今天鹏哥就带来js中的复制方法。 JS中对象...

网友评论

    本文标题:小议iOS中的浅复制和深复制

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