前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS中的浅复制与深复制

iOS中的浅复制与深复制

作者头像
Cloudox
发布2021-11-23 14:23:18
5050
发布2021-11-23 14:23:18
举报
文章被收录于专栏:月亮与二进制月亮与二进制

当谈到对象复制时都绕不开浅复制与深复制的区分,它们是什么意思呢?

  • 浅复制:只复制对象的指针,两个对象指向的还是同一个地址的内容,操作一个时会影响另一个的值。
  • 深复制:复制对象的内容,两个对象指向两个不同地址的内容,操作一个时不会影响另一个的值。

在OC中,因为采用内存计数的方式管理内存,所以浅复制时会对同一个内容计数加一,深复制则不会。

在OC中,复制操作有copy和mutableCopy两种方法,那哪种是浅复制哪种是深复制呢?

非集合对象

先把对象大致分为两类:非集合对象与集合对象,至于为什么要这么分,待会讲集合对象的时候再说。

非集合对象就是指NSString、NSNumber等本身就是具体内容的对象。像NSString这种对象,还有一个相关的叫NSMutableString。所以在非集合对象中又可以分为可变对象和不可变对象。

对他们进行copy与mutableCopy的含义是:

  • 对于不可变非集合对象(如NSString),copy操作是浅复制,只会复制指针,mutableCopy操作是深复制,
  • 对于可变非集合对象(如NSMutableString),copy和mutableCopy都是深复制,都会创建一个新的同样的内容来返回,但是要注意,copy返回的是不可变对象,也就是说即使你对一个NSMutableString做copy操作,返回给另一个NSMutableString,然后去对这个NSMutableString做变化操作,会报错。

用代码来看如下:

代码语言:javascript
复制
NSString *string = @"origin";
NSString *stringCopy = [string copy];// 浅复制
NSMutableString *stringMCopy = [string mutableCopy];// 深复制

NSMutableString *string = [NSMutableString stringWithString: @"origin"];
NSString *stringCopy = [string copy];// 深复制
NSMutableString *mStringCopy = [string copy];// 深复制
NSMutableString *stringMCopy = [string mutableCopy];// 深复制
[mStringCopy appendString:@"mm"]; // crash

集合对象

上面说了非集合对象,那什么是集合对象呢?集合对象就是指NSArray、NSDictionary、NSSet这些包含其他对象的对象。

为什么要做这个区分呢?因为浅复制、深复制这两个概念其实并不完全,更准确的应该分为三种:浅复制、深复制、完全深复制。

在OC中,当你对一个集合对象做深复制时,这个深复制只是单层的,集合内的元素对象其实还只是引用,并不是每一层都是深复制,这一情况,苹果定义为单层深复制(one-level-deep copy)。只有对集合内的每一层都去做深复制,才能够称为完全深复制。

先说说简单的浅复制与深复制,其实与非集合对象差不多:

  • 对于不可变集合对象(如NSArray),copy操作是浅复制,只会复制指针,mutableCopy操作是深复制,
  • 对于可变集合对象(如NSMutableArray),copy和mutableCopy都是深复制,都会创建一个新的同样的内容来返回,但是要注意两点,一是copy返回的还是不可变对象,二就是上面说的,这个深复制只是单层深复制,里面包含的元素还是指针浅复制。

代码来说就是:

代码语言:javascript
复制
NSArray *array = @[@[@"a", @"b"], @[@"c", @"d"];
NSArray *copyArray = [array copy];// 浅复制
NSMutableArray *mCopyArray = [array mutableCopy];// 单层深复制

NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];
NSArray *copyArray = [array copy];// 单层深复制,返回不可变对象
NSMutableArray *mCopyArray = [array mutableCopy];// 单层深复制

那如果要做完全深复制该怎么做呢?

有两种方法:

  • 一种是用如下所示的方法:
代码语言:javascript
复制
NSDictionary shallowCopyDict = [[NSDictionary alloc] initWithDictionary:someDictionary copyItems:YES];

copyItems设为YES会对集合中的每一个对象尝试做深复制,但是要求集合中的元素对象遵循NSCopying 协议,否则就会报错。但这其实还是对元素这一层的单层深复制,再下去也没有完全深复制。

代码语言:javascript
复制
NSArray *trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:oldArray]];

以上就是OC中浅复制与深复制的各种应用了,要自己测试到底操作是浅复制还是深复制,可以通过看对象的引用计数是否增加:

代码语言:javascript
复制
NSLog(@"mArray retain count: %d", [mArray retainCount]);// ARC下不可用

或者直接看两个对象的地址是否一致:

代码语言:javascript
复制
NSLog(@"string自身指针的地址:%x", &str);
NSLog(@"string指针指向的对象的地址:%p", str);

查看作者首页

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017/11/27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 非集合对象
  • 集合对象
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档