很多语言中都有深复制浅复制的概念,如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. sqlmap批量扫描burpsuite请求日志记录

    sqlmap可以批量扫描包含有request的日志文件,而request日志文件可以通过burpsuite来获取, 因此通过sqlmap结合burpsuite工具,可以更加高效的对应用程序是否存在SQ ...

  2. 捉虫记2:windows程序句柄泄露的上下文环境

    作为程序员,开发程序是基本功,而调试程序也是必不可少的技能之一.软件在主体功能开发完成后会经历各个阶段的测试,才会被发布.在测试过程中,出现较多的可能就是内存泄漏,句柄泄漏,异常崩溃等属于非功能型的软 ...

  3. foreman1.3安装

    一.环境: centos 6.3 64bit 二.安装yum源: rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release ...

  4. 【转】Picasso – Android系统的图片下载和缓存类库

    来源:http://blog.chengyunfeng.com/?p=492 另一篇参考:http://blog.csdn.net/xu_fu/article/details/17043231 Pic ...

  5. js快速打印一个五分制(五颗星)的评分情况

    1.函数 下面这个函数实现了在html页面中快速打印一个五分制(五颗星)的评分情况: function getRating(rating) { if(rating > 5 || rating & ...

  6. Android 之 内存管理-查看内存泄露(三)

    概述 在android的开发中,要时刻主要内存的分配和垃圾回收,因为系统为每一个dalvik虚拟机分配的内存是有限的,在google的G1中,分配的最大堆大小只有16M,后来的机器一般都为24M,实在 ...

  7. 使用JRockit进行性能优化一:环境搭建

    1. jrockit简介   jrockit前身是BA jrockit,后被oracle收购,并免费发布,但并不开源.   jrockit可以看做是兼容标准的JDK基础上的JVM,同原有的JVM相比, ...

  8. poj2478

    比较简单的树形dp; 定义s[i]为节点i的子树节点数和(包括自身):叶子节点s[j]=1; s[i]=signma(s[k])+1 (k是i的孩子) 则i满足的条件是 1.s[k]<=n di ...

  9. Dubbo实例

    1. Dubbo是什么? Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案.简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需 ...

  10. Skyline学习教程

    转自:http://yunjinzh.blog.sohu.com/165279318.html 当初开设这个blog的初衷就是将PPT与专业技术进行结合 将专业技术的介绍更加艺术化 但是之前一直都没有 ...