深拷贝与浅拷贝区别

浅拷贝:浅拷贝是指针拷贝,对一个实现NSCopying协议的对象进行浅拷贝,会创建一个新的指针来指向原始对象。两个指针指向同一个内存区域,如果原始对象的内容发生改变,新的对象同样会发生改变;新的对象内容变化,原始对象内容也会发生变化。如图所示:


image.png

深拷贝:深拷贝是内容拷贝,他会把原始对象的内容复制出来,然后让这个内容放到新的对象里面。两个指针指向不同的内存区域,原始对象的内容变化不影响新的对象;新的对象内容变化也不影响原始对象。


image.png

验证上述深拷贝和浅拷贝的代码:

    //深拷贝示例:
    //str内容改变的时候,strCopy内容并没有发生变化
    NSMutableString *str = [NSMutableString stringWithFormat:@"123"];
    NSString *strCopy = [str copy];
    NSLog(@"str:%@, strCopy:%@", str, strCopy);
    [str appendFormat:@"123"];
    NSLog(@"str:%@, strCopy:%@", str, strCopy);
2018-06-26 15:10:21.825600+0800 CopyTest[14774:1661930] str:123, strCopy:123
2018-06-26 15:10:21.825816+0800 CopyTest[14774:1661930] str:123123, strCopy:123
    //想要使用copy方法的条件:必须遵守<NSCopying>协议,实现 copyWithZone: 方法
    NSMutableArray *muArr = [NSMutableArray array];
    NSArray *arr = [NSArray array];
    
    NSString *str = [NSString string];
    NSMutableString *muStr = [NSMutableString string];
    
    NSDictionary *dic = [NSDictionary dictionary];
    NSMutableDictionary *muDic = [NSMutableDictionary dictionary];
    
    //拷贝出来对象的类型
    //数组
    NSLog(@"%@", [arr.copy class]);
    NSLog(@"%@", [arr.mutableCopy class]);
    NSLog(@"%@", [muArr.copy class]);
    NSLog(@"%@", [muArr.mutableCopy class]);
    
    //字符串
    NSLog(@"%@", [str.copy class]);
    NSLog(@"%@", [str.mutableCopy class]);
    NSLog(@"%@", [muStr.copy class]);
    NSLog(@"%@", [muStr.mutableCopy class]);
    
    //字典
    NSLog(@"%@", [dic.copy class]);
    NSLog(@"%@", [dic.mutableCopy class]);
    NSLog(@"%@", [muDic.copy class]);
    NSLog(@"%@", [muDic.mutableCopy class]);
    
    //拷贝出来对象的内存地址比较
    //数组
    NSLog(@"数组:%p, %p", arr, arr.copy); //浅拷贝
    NSLog(@"数组:%p, %p", arr, arr.mutableCopy); //深拷贝
    NSLog(@"数组:%p, %p", muArr, muArr.copy); //深拷贝
    NSLog(@"数组:%p, %p", muArr, muArr.mutableCopy); //深拷贝
    
    
    //字符串
    NSLog(@"字符串:%p, %p", str, str.copy); //浅拷贝
    NSLog(@"字符串:%p, %p", str, str.mutableCopy); //深拷贝
    NSLog(@"字符串:%p, %p", muStr, muStr.copy); //深拷贝
    NSLog(@"字符串:%p, %p", muStr, muStr.mutableCopy); //深拷贝
    
    //字典
    NSLog(@"字典:%p, %p", dic, dic.copy); //浅拷贝
    NSLog(@"字典:%p, %p", dic, dic.mutableCopy); //深拷贝
    NSLog(@"字典:%p, %p", muDic, muDic.copy); //深拷贝
    NSLog(@"字典:%p, %p", muDic, muDic.mutableCopy); //深拷贝
2018-06-26 14:51:41.168790+0800 CopyTest[14400:1606517] __NSArray0
2018-06-26 14:51:41.168990+0800 CopyTest[14400:1606517] __NSArrayM
2018-06-26 14:51:41.169081+0800 CopyTest[14400:1606517] __NSArray0
2018-06-26 14:51:41.169164+0800 CopyTest[14400:1606517] __NSArrayM
2018-06-26 14:51:41.169285+0800 CopyTest[14400:1606517] __NSCFConstantString
2018-06-26 14:51:41.169516+0800 CopyTest[14400:1606517] __NSCFString
2018-06-26 14:51:41.169615+0800 CopyTest[14400:1606517] __NSCFConstantString
2018-06-26 14:51:41.169731+0800 CopyTest[14400:1606517] __NSCFString
2018-06-26 14:51:41.169834+0800 CopyTest[14400:1606517] __NSDictionary0
2018-06-26 14:51:41.169940+0800 CopyTest[14400:1606517] __NSDictionaryM
2018-06-26 14:51:41.170034+0800 CopyTest[14400:1606517] __NSFrozenDictionaryM
2018-06-26 14:51:41.170149+0800 CopyTest[14400:1606517] __NSDictionaryM
2018-06-26 14:51:41.170261+0800 CopyTest[14400:1606517] 数组:0x60400001e0a0, 0x60400001e0a0
2018-06-26 14:51:41.170340+0800 CopyTest[14400:1606517] 数组:0x60400001e0a0, 0x604000049270
2018-06-26 14:51:41.170457+0800 CopyTest[14400:1606517] 数组:0x6040000587b0, 0x60400001e0a0
2018-06-26 14:51:41.170564+0800 CopyTest[14400:1606517] 数组:0x6040000587b0, 0x60000044e430
2018-06-26 14:51:41.170790+0800 CopyTest[14400:1606517] 字符串:0x10075c320, 0x10075c320
2018-06-26 14:51:41.170963+0800 CopyTest[14400:1606517] 字符串:0x10075c320, 0x60000044e430
2018-06-26 14:51:41.171171+0800 CopyTest[14400:1606517] 字符串:0x604000058d20, 0x101666030
2018-06-26 14:51:41.171391+0800 CopyTest[14400:1606517] 字符串:0x604000058d20, 0x604000049270
2018-06-26 14:51:41.171873+0800 CopyTest[14400:1606517] 字典:0x60400001e090, 0x60400001e090
2018-06-26 14:51:41.172208+0800 CopyTest[14400:1606517] 字典:0x60400001e090, 0x604000425140
2018-06-26 14:51:41.172415+0800 CopyTest[14400:1606517] 字典:0x60400003dc20, 0x604000425140
2018-06-26 14:51:41.172520+0800 CopyTest[14400:1606517] 字典:0x60400003dc20, 0x604000425140

根据上面代码输出内容可以总结出如下结论:copy拷贝出来的对象类型总是不可变类型
image.png
image.png

延伸:在写代码的时候碰到一个有趣的现象,深拷贝改变了原始数据内容,新的内容依然改变。

    NSMutableArray *arr = [NSMutableArray array];
    NSMutableArray *subArr = [NSMutableArray array];
    [subArr addObject:@"1"];
    [arr addObject:subArr];
    NSMutableArray *muArr = [arr mutableCopy]; //深拷贝
    NSLog(@"arr:%@, muArr:%@", arr, muArr);
    [subArr addObject:@"2"];
    NSLog(@"arr:%@, muArr:%@", arr, muArr);
2018-06-26 15:36:05.813570+0800 CopyTest[15167:1736602] arr:(
        (
        1
    )
), muArr:(
        (
        1
    )
)
2018-06-26 15:36:05.813769+0800 CopyTest[15167:1736602] arr:(
        (
        1,
        2
    )
), muArr:(
        (
        1,
        2
    )
)

猜测:这里的数组相当于一个容器里面套了一个容器。深拷贝的限制只是针对外层的容器而言的,对里面的容器并没有限制。
我们通过代码来验证一下:

    NSMutableArray *arr = [NSMutableArray array];
    NSMutableArray *subArr = [NSMutableArray array];
    [subArr addObject:@"1"];
    [arr addObject:subArr];
    NSMutableArray *muArr = [arr mutableCopy]; //深拷贝
    NSLog(@"arr:%@, muArr:%@", arr, muArr);
    [muArr addObject:@"2"];
    NSLog(@"arr:%@, muArr:%@", arr, muArr);
2018-06-26 15:42:04.404419+0800 CopyTest[15287:1755382] arr:(
        (
        1
    )
), muArr:(
        (
        1
    )
)
2018-06-26 15:42:04.404628+0800 CopyTest[15287:1755382] arr:(
        (
        1
    )
), muArr:(
        (
        1
    ),
    2
)

我们给拷贝出来的新数组外层添加一个数据@“2”,运行出来的结果跟我们预测一样,只是新数组发生了变化。原始数组的数据依然不变。这里可以看做不完全深拷贝,我们平常使用的一般都是不完全深拷贝。想要实现完全深拷贝需要重写copyWithZone:方法来实现。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容