Copy(二):深拷贝

如果觉得我写的还不错,请关注我的新浪微博@杨浩宇-小橘爷,最新文章即时推送~

浅拷贝与深拷贝

在上一篇文章中,我们了解了 copy 的基础知识和实现方法。对于数组来说,其中放置的可能是不可变字符串(常量字符串对象是不可变的)。当我们使用可变字符串代替不可变字符串填充数组时,数组中的字符串就是可以改变的了。

当我们使用 mutableCopy 方法对装满了可变字符串的数组进行了拷贝之后,修改原始的数组的第一个字符串的值,你会发现,拷贝的字符串的第一个值也发生了改变。或许你能够理解为什么 dataArray 的第一个元素发生改变,但不明白为什么它的副本也会改变。从集合中获取元素时,就得到了这个元素的一个新引用,但并不是一个新副本。所以 dataArray[0] 返回的对象与 dataArray 中的第一个元素都指向内存中的同一个对象。随后,修改字符串对象的副作用就是同时改变了 dataArray 的第一个元素。

为什么你制作的副本的第一个元素也发生了改变?这与默认的浅复制方式有关。它意味着使用 mutableCopy 方法复制数组时,在内存中为新的数组对象分配了空间,并将单个元素复制到新数组中。然而将原始数组中的每个元素复制到新位置意味着:仅将引用从一个数组元素复制到另一个数组元素。这样做的最终结果,就是这两个数组中的元素都指向内存中的同一个字符串。这与将一个对象赋值给另一个对象没有区别。

若要为数组中的每个元素创建完全不同的副本,需要执行所谓的深拷贝。这就意味着要创建数组中的每个对象内容的副本,而不仅仅是这些对象的引用副本(并且考虑一下,如果数组中的元素本身是数组对象,深复制意味着该如何处理)。然而使用 Foundation 类的 copy 和 mutableCopy 方法时,深复制并不是默认执行的。

使用归档深拷贝对象

在之前,我们尝试创建了包含可变字符串元素的数组副本,并且了解了如何进行浅复制。也就是说,没有复制实际的字符串本身,只是复制对它们的引用。

可以使用 Foundation 的归档功能来创建对象的深复制。例如,通过 dataArray 归档到一个缓冲区,然后把它解归档,将结果指派给 dataArray2,从而 dataArray 复制给 dataArray2。对于这个过程,不需要使用文件,归档和解归档过程都可以在内存中发生。
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSData *data;
        NSMutableArray *dataArray = [NSMutableArray arrayWithObjects:
            [NSMutableString stringWithString:@"one"],
            [NSMutableString stringWithString:@"two"],
            [NSMutableString stringWithString:@"three"],
            nil
        ];
    
        NSMutableArray *dataArray2;
        NSMutableString *mStr;
    
        // 使用归档进行深拷贝
    
        data = [NSKeyedArchiver archivedDataWithRootObject:dataArray];
        dataArray2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    }
    return 0;
}

上述代码中的复制操作是通过以下两行来实现的:

data = [NSKeyedArchiver archivedDataWithRootObject:dataArray];
dataArray2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];

甚至可以避免中间赋值,只用一条语句来执行复制,语句如下:

dataArray2 = [[NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:dataArray]];

下次需要生成一个对象(或不支持 NSCopying 协议的对象)的深复制时,应该记住这项技术。

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

推荐阅读更多精彩内容