Objective-C中的深拷贝和浅拷贝

1.浅拷贝

所谓的浅拷贝,就是指只是将对象内存地址多了一个引用,也就是说,拷贝结束之后,两个对象的值不仅相同,而且对象所指的内存地址都是一样的。

2.单层深拷贝

对于不可变的容器类对象(如NSArray、NSSet、NSDictionary)进 mutableCopy 操作,内存地址发生了变化,但是其中的元素内存地址并没有发生变化,属于单层深拷贝。 对于可变集合类对象(如NSMutableArray、NSMutableSet、NSMutableDictionary),不管是进行 copy 操作还是 mutableCopy 操作,其内存地址都发生了变化,但是其中的元素内存地址都没有发生变化,属于单层深拷贝。

3.深拷贝

所谓深拷贝,就是指拷贝一个对象的具体内容,拷贝结束之后,两个对象的值虽然是相同的,但是指向的内存地址是不同的。两个对象之间也互不影响,互不干扰。

@property (nonatomic, strong) NSArray *array0;                      // 不推荐写法

@property (nonatomic, copy) NSArray *array1;                        // 推荐写法

@property (nonatomic, strong) NSMutableArray *array2;         // 推荐写法

@property (nonatomic, copy) NSMutableArray *array3;           // 错误写法

像NSArray,NSDictionary,NSMString等推荐使用copy修饰, 如果传递的是 NSArray 对象,则只是对原先对象的一份强引用(应该是编译器优化的),但是如果传递的是 NSMutableArray 对象,则是对原先对象的一次“单层深拷贝”,生成的 NSArray 对象是一份新内存地址的对象,但是其中的元素还是原先的。

retain:始终是浅复制。引用计数每次加一。返回对象是否可变与被复制的对象保持一致。

copy:对于可变对象为深复制,引用计数不改变;对于不可变对象是浅复制, 引用计数每次加一。始终返回一个不可变对象。  

mutableCopy:始终是深复制,引用计数不改变。始终返回一个可变对象。

因为⽗父类指针可以指向⼦子类对象,使⽤用 copy 的⽬目的是为了了让本对象的属性不不受外界影响,使⽤ copy ⽆无论给我传⼊是一个可变对象还是不可对象,我本身持有的就是一个不可变的副本.

如果我们使用是 strong ,那么这个属性就有可能指向⼀个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性.

copy 此特质所表达的所属关系与 strong 类似。然而设置⽅法并不保留新值,⽽是将其“拷贝” (copy)。 当属性类型为 NSString 时,经常⽤此特质来保护其封装性,因为传递给设置方法的新值有可能指向一个 NSMutableString 类的实例。这个类是NSString 的⼦类,表示一种可修改其值的字符串,此时若是不拷⻉字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份“不可变” (immutable)的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是“可变的” (mutable),就应该在设置新属性值时拷⻉⼀份。

1. 对⾮非集合类对象的copy操作:

在⾮集合类对象中:对 immutable 对象进行 copy 操作,是指针复制,mutableCopy操作时内容复制;

对 mutable 对象进行 copy 和 mutableCopy 都是内容复制。

⽤代码简单表示如下:

[immutableObject copy] // 浅复制

[immutableObject mutableCopy] //深复制

[mutableObject copy] //深复制

[mutableObject mutableCopy] //深复制

⽐如以下代码:

NSMutableString *string = [NSMutableString stringWithString:@"origin"];//copy

NSString *stringCopy = [string copy];

查看内存,会发现 string、stringCopy 内存地址都不一样,说明此时都是做内容拷贝、深拷贝。即使你进行如下操作:

[string appendString:@"origion!"]

stringCopy 的值也不会因此改变,但是如果不使用 copy,stringCopy 的值就会被改变。 集合类对象以此类推。

 所以,用 @property 声明 NSString、NSArray、NSDictionary 经常使用 copy 关键字,是

因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary,他们之间可能进行赋值操作,为确保对象中的字符串值不会无意间变动,应该在设置新属性值时拷⻉一份。

2、集合类对象的copy与mutableCopy

集合类对象是指 NSArray、NSDictionary、NSSet ... 之类的对象。下⾯先看集合类

immutable对象使⽤用 copy 和 mutableCopy 的⼀个例子:

NSArray *array = @[@[@"a", @"b"], @[@"c", @"d"]];  

NSArray *copyArray = [array copy];  //

NSMutableArray *mCopyArray = [array mutableCopy];

查看内容,可以看到 copyArray 和 array 的地址是一样的,⽽ mCopyArray 和 array的地址是不同的。说明 copy 操作进⾏了指针拷贝,mutableCopy 进⾏了内容拷贝。但需要强调的是:此处的内容拷贝,仅仅是拷贝 array 这个对象,array 集合内部的元素仍然是指针拷贝。这和上面的非集合 immutable 对象的拷⻉还是挺相似的,那么mutable对象的拷贝会不会类似呢?我们继续往下,看 mutable 对象拷贝的例子:

NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableStringstringWithString:@"a"],@"b",@"c",nil];

NSArray *copyArray = [array copy];

NSMutableArray *mCopyArray = [array mutableCopy];查看内存,如我们所料,copyArray、mCopyArray和 array 的内存地址都不一样,说明 copyArray、mCopyArray 都对 array 进⾏了内容拷贝。同样,我们可以得出结论:

在集合类对象中,对 immutable 对象进行 copy,是指针复制, mutableCopy 是内

容复制;对 mutable 对象进行 copy 和 mutableCopy 都是内容复制。但是:集合对

象的内容复制仅限于对象本身,对象元素仍然是指针复制。⽤代码简单表示如下:

[immutableObject copy] // 浅复制

[immutableObject mutableCopy] //单层深复制

[mutableObject copy] //单层深复制

[mutableObject mutableCopy] //单层深复制

这个代码结论和非集合类的非常相似。

举例:

 // 测试深复制于浅复制

    self.dataArr = [NSMutableArray array];

    NSMutableString *str1 = [NSMutableString string];

    [str1 appendFormat:@"a"];

    [str1 appendFormat:@"b"];

    NSLog(@"str1:%@",str1);

    // self.string = str1;  // string的属性用copy  改变str1的时候才不会影响string

    [self.dataArr addObject:str1];

    NSLog(@"dataArr:%@",_dataArr);

    self.dataArrSuper = [NSArray arrayWithArray:self.dataArr]; // arrayWithArray 是深拷贝 dataArrSuper对dataArr进行深拷贝, 如果没有 self.string = str1(且self.string 的属性使用copy) 这一步 对于dataArr内部的str1还是浅拷贝

    NSLog(@"dataArr:%p dataArrSuper:%p",self.dataArr,self.dataArrSuper);

    NSLog(@"%p",str1);

    NSLog(@"dataArr中的str1:%p dataArrSuper的str1:%p",self.dataArr[0],self.dataArrSuper[0]);

    NSLog(@"dataArrSuper:%@",_dataArrSuper);

// 此下为对集合类对象的深复制与浅复制测试

    [_dataArr addObject:@"c"];  // 这是对dataArr数组本身操作,不会影响dataArrSuper;

    [str1appendFormat:@"d"];  // dataArr内部可变字符串改变, 会影响dataArrSuper

    NSLog(@"后dataArr:%@",_dataArr);

    NSLog(@"后dataArrSuper:%@",_dataArrSuper);


打印结果

总结一下:

1.用@property声明的NSString(或NSArray,NSDictionary)推荐使用copy关键

2.非集合类:只有不可变对象进行copy操作时是浅复制([immutableObject copy] // 浅复制),其他都是深复制

3.集合类:只有不可变对象进行copy操作时是浅复制([immutableObject copy] // 浅复制),其他都是单层深复制(参考本文最上方单层深复制解释)

俗话说:“好记性不如烂笔头”,如果咬文嚼字认真看了一遍还是觉得模棱两可的话,建议亲自敲一小段代码尝试一下,查看一下其内容的变化,会对你印象更深刻。

如果有什么问题,欢迎大家批评指正,我们一同走上溜光大道!!!

你拼命赚钱的样子虽然有些狼狈,但是你靠自己的样子真的很美!加油

基于Mac terminal 上传本地项目到github

iOS应用打包上传流程

升级Xcode 10后#import 没有头文件提示

关于sourceTree从URL克隆遇到的问题

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

推荐阅读更多精彩内容