很多语言中都有深复制浅复制的概念,如C++,ObjC等。简单来说,浅复制就是两个变量指向了同一块内存区域,深复制就是两个变量指向了不同的内存区域,但是两个内存区域里面的内容是一样的。

浅复制示意图:

深复制示意图:

iOS开发中,浅复制和深复制要更复杂一些,涉及到集合对象和非集合对象的copy与mutableCopy。

非集合对象:如NSString,NSInteger,NSNumber……

集合对象:如NSArray,NSDictionary,……

1:非集合对象的copy与mutableCopy。

非集合对象的copy与mutableCopy,只需要遵循以下规则即可:

  (1)可变对象的copy和mutableCopy方法都是深复制

  (2)不可变对象的copy方法是浅复制,mutableCopy方法是深复制

  (3)copy方法返回的对象是不可变对象

下面通过代码来验证:

可变对象的copy与 mutableCopy方法:

void testMutable()
{
//可变对象的复制,copy和mutableCopy都是深拷贝
NSMutableString *str1 = [NSMutableString stringWithString:@"test"];
NSMutableString *str2 = [str1 copy];
//copy返回的是不可变对象,因此str2不能改变,会发生崩溃
//[str2 appendString:@"test"];
NSMutableString *str3 = [str1 mutableCopy];
[str3 appendString:@"test"];
NSLog(@"%@ %@ %@",str1,str2,str3);
NSLog(@"%p %p %p",str1,str2,str3);
}

执行结果:

可以看到,三个字符串的地址是不相同的,说明copy和 mutableCopy方法都是深复制。

不可变对象的copy与mutableCopy方法:

void testNoMutable()
{
NSString *str1 = @"test";
//直接copy是浅复制
NSMutableString *str2 = [str1 copy];
//copy返回的是不可变对象,str2不能被修改,因此会发生崩溃
//[str2 appendString:@"test"];
//mutableCopy是深复制
NSMutableString *str3 = [str1 mutableCopy];
[str3 appendString:@"test"];
NSLog(@"%@ %@ %@",str1,str2,str3);
NSLog(@"%p %p %p",str1,str2,str3);
}

执行结果:

可以看到:前两个地址一样,第三个地址不一样,因此不可变对象的copy方法是浅复制,mutableCopy方法是深复制。

另外需要注意:无论是可变对象还是不可变对象,copy 方法返回的对象都是不可变的。

2:集合对象的copy与mutableCopy

实际上,集合对象与非集合对象所遵循的规则基本上是一样的。

可变对象的的copy与mutableCopy 方法

验证代码:

void testSetMutable()
{
NSMutableArray *array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c", nil];
//可变对象copy是深复制
NSMutableArray *array2 = [array1 copy];
//copy返回的是不可变对象,array2不能被修改,因此会崩溃
//[array2 addObject:@"d"];
//可变对象的mutableCopy是深复制
NSMutableArray *array3 = [array1 mutableCopy];
[array3 addObject:@"d"];
NSLog(@"%p %p %p",array1,array2,array3);
}

执行结果:

可以看到地址是不一样的。说明可变对象的copy和mutableCopy方法都是深复制。

不可变对象的copy与mutableCopy方法

验证代码:

void testSetNoMutable()
{
NSArray *array1 = @[@"a",@"b",@"c"];
//不可变对象的copy方法,浅复制
NSArray *array2 = [array1 copy];
//不可变对象的mutableCopy方法,深复制
NSArray *array3 = [array1 mutableCopy];
NSLog(@"%p %p %p",array1,array2,array3);
}

执行结果:

可以看到,前两个地址一样,第三个地址不一样。说明不可变对象的copy方法是浅复制,mutableCopy方法是深复制。

集合对象和非集合对象的一个差别:

上面说的集合对象的深复制并不是严格意义上的深复制,而是单层深复制。

单层深复制:对集合对象来说,深复制时只是将第一层对象进行了深复制,内部的对象仍然是浅复制。比如说

NSMutableArray *array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c", nil];

调用copy方法   NSArray *array2 = [array1 copy] ,有分配了一块内存,array2指向了这块内存,但是数组内部的元素,指向的仍然是数组1内部的元素,即内部元素是浅复制。

验证代码:

void testSetMutable()
{
NSMutableArray *array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c", nil];
//可变对象copy是深复制
NSMutableArray *array2 = [array1 copy];
//copy返回的是不可变对象,array2不能被修改,因此会崩溃
//[array2 addObject:@"d"];
//可变对象的mutableCopy是深复制
NSMutableArray *array3 = [array1 mutableCopy];
[array3 addObject:@"d"];
NSLog(@"%p %p %p",array1,array2,array3);
NSLog(@"%p %p %p",array1[],array2[],array3[]);
}

执行结果:

可以看到,三个数组的第一个元素的地址是一样的,也就是说内部元素是浅复制。

3:集合对象的完全复制

集合对象的完全复制,就是集合中的每一层的元素都是深复制。

方法一:

使用 initWith***: copyItems:YES  方法。

代码:

void testFullCopy()
{
NSMutableArray *array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c", nil];
NSArray *array2 = [[NSArray alloc] initWithArray:array1 copyItems:YES];
NSLog(@"%p %p",array1,array2);
NSLog(@"%p %p",array1[],array2[]);
}

执行结果:

可以看到数组元素的地址不一样。

方法二:

先将集合进行归档,然后再解档。代码如下:

void testFullCopy2()
{
NSMutableArray *array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c", nil];
NSArray *array2 = [NSKeyedUnarchiver unarchiveTopLevelObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array1 ] error:nil];
NSLog(@"%p %p",array1,array2);
NSLog(@"%p %p",array1[],array2[]);
}

执行结果:

可以看到数组元素的地址不一样。

iOS中的深复制与浅复制的更多相关文章

  1. iOS 集合的深复制与浅复制

    概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对象内存到另一块内存中. 一图以蔽之 再简单些说:浅复制就是指针拷贝:深复制 ...

  2. Java中对象的深复制和浅复制详解

    1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵ ...

  3. Java中的深复制与浅复制

    1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不 复制它所引用的对象. ...

  4. C#中的深复制与浅复制

    C#中分为值类型和引用类型,值类型的变量直接包含其数据,而引用类型的变量则存储对象的引用. 对于值类型,每个变量都有自己的数据副本,对一个变量的操作不可能影响到另一个变量.如 class Progra ...

  5. Java中的clone()----深复制,浅复制

    这篇文章主要介绍了Java中对象的深复制(深克隆)和浅复制(浅克隆) ,需要的朋友可以参考下 1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他 ...

  6. js中的深复制与浅复制

    前言 所谓深复制与浅复制(深拷贝与浅拷贝),乍一听感觉听高大上,像是一个非常难理解的概念,其实我们平常项目开发都是在用的,只是你可能不知道该怎么叫它的名字而已,就像你听熟了一首歌,就是不知道这首歌叫什 ...

  7. js中的深复制和浅复制

    在实际情况中经常会遇到对对象复制的问题.比如在处理项目中的一笔多结构的数据存储或者调用,这个时候你就要对对象(json)进行操作,而不同的操作根据不同的需求来定义.其中最常见最普遍的是对对象的复制,重 ...

  8. iOS 之 深复制、浅复制

    深复制不仅复制对象本身,对象持有的属性对象也做了复制. 浅复制之复制对象本身,不对里面的属性进行复制.

  9. 深复制与浅复制&&strong,copy修饰符总结

    又是一个老生常谈的话题,可是貌似这个问题,好多ios开发工程师并不能理解透彻,所以简单记录分析一下深复制与浅复制的原理以及strong,copy修饰符的原理和使用.   一.深复制与浅复制      ...

  10. .Net深复制、浅复制

    在.Net,大家都知道引用类型的深复制.浅复制吧. ,一般int等值类型是值类型(复制时是直接传值),一般的类(List<T>,Class)是引用类型(复制时传地址),默认是浅复制.若ob ...

随机推荐

  1. 【算法】 输入n 输出一个n*n的zigzag矩阵 利用c++实现

    int main() { int N; cin>>N; int **a = new int *[N]; ) ;//如果没有申请到空间 ;i<N;i++) { a[i]= new in ...

  2. C#.Net 如何动态加载与卸载程序集(.dll或者.exe)3---- 动态加载Assembly应用程序

    下载 supergraphfiles.exe 示例文件. 应用程序体系结构 在我专攻代码之前,我想谈谈我尝试做的事.您可能记得,SuperGraph 让您从函数列表中进行选择.我希望能够在具体的目录中 ...

  3. Linux下执行程序出现 Text file busy 提示时的处理方式

    使用 fuser xxx 命令查看xxx文件被哪个进程占用,然后关闭该进程,解决问题. # fuser xxxxxx:              2878# kill -9 2878 注:xxx是文件 ...

  4. Android开发之ListView-SimpleAdapter的使用

    SimpleAdapter: SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int r ...

  5. 如何把Excel另存为XML格式文件(快速转换)

    这时,我们尝试另存为另一种文件类型: XML电子表格2003(*.xml)

  6. php 类 成员变量 $this->name='abc'

    <?php class test { public function getName() { $this->name='abc'; echo $this->name; } }$a=n ...

  7. 2009国家集训队小Z的袜子

    莫队算法? 感觉没什么优越性啊?难道就是因为在排序的时候cmp函数的不同?这样做为什么减少时限啊? 我带着疑惑敲了代码,却一直有bug…… 代码: type node=record l,r,id,x, ...

  8. Java String 的equals, == , hascode的区别

    1.equals 和 == ==在java中是比较引用的,即在内存中的地址.而String的equals()是比较字符串的内容 http://blog.csdn.net/barryhappy/arti ...

  9. 【转】Android AlertDialog 点击对话框外部区域不关闭的设置

    原文网址:http://blog.sina.com.cn/s/blog_8f1c79dd0101a63u.html 在Android开发中,常常需要调用对话框,但会遇到这样一种情况,在显示对话框的时候 ...

  10. jquery自动焦点图

    效果预览:http://runjs.cn/detail/vydinibc  带左右箭头的自动焦点图:http://runjs.cn/detail/wr1d1keh html: <div clas ...