copy,retain,strong的区别

      之前的编码中,对于NSString的property修饰,习惯性使用copy,只是粗略的知道copy属于深复制,retain/strong属于浅复制,并没有对其深究。最近需要详细了解这一块知识,在网上搜索相关内容,并且用代码验证,查看对比了内存地址,做一些总结。

        一、之前对于copy和retain/strong的区别理解是这样的:

        copy是复制了源对象所在内存空间的数据,放入目的对象指针指向的内存空间,并且令目的对象引用计数为1,对于源对象的引用计数没有影响;源对象内容的改变不会影响到目的对象。

       retain/strong是目的对象指针指向源对象的内存空间,源对象的引用计数+1;源对象的改变会影响到目的对象。

       

      mutablecopy返回的是可变的对象,copy返回的是不可变的对象。


       二、代码验证探究

     1、源对象为不可变 NSString

   

[objc]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. NSString*str = @"test";  
  2. NSString* retainStr = [str retain];  
  3. NSString* copyStr = [str copy];  
  4. NSMutableString* mcopyStr = [str mutableCopy];  
  5. NSLog(@"str addr = %p",str);  
  6. NSLog(@"retainStr addr = %p",retainStr);  
  7. NSLog(@"copyStr addr = %p",copyStr);  
  8. NSLog(@"mcopyStr addr = %p",mcopyStr);  
输出如下:

       

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. str addr = 0x4598  
  2. retainStr addr = 0x4598  
  3. copyStr addr = 0x4598  
  4. mcopyStr addr = 0x8caf630  

分析:

retain的对象毫无悬念,还是源对象的内存地址;

copy的对象和我原来想的不一样,竟然和retain一样,也是源对象地址;这意味者并没有对源对象内容进行复制,而只是复制了指针而已。如此看来copy方法并不一定会复制源对象的内容。之所以复制,肯定是因为两个版本有所不同。而这里源对象是NSString不可变的,copy返回的也是不可变的,既然都不可变,那么这里的副本就没有多大意义存在,就如同使用字符串常量,系统会为我们优化,声明多个字符串,都是不可变且内容相同,那么系统就只申请一块内存,这个道理是一样的。指向一块内存就可以了,所以这里的copy和retain的作用是一样的。

mutablecopy的对象地址和源对象地址不同,说明重新开辟了内存,复制了一个副本。因为mutablecopy返回的对象是可变的,它的变动会影响到源对象,所以需要拷贝一份。


源对象为可变的NSMutableString

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. NSMutableString* str = [NSMutableString stringWithString:@"test"];  
  2. NSString* retainStr = [str retain];  
  3. NSString* copyStr = [str copy];  
  4. NSMutableString* mcopyStr = [str mutableCopy];  
  5. NSLog(@"str addr = %p",str);  
  6. NSLog(@"retainStr addr = %p",retainStr);  
  7. NSLog(@"copyStr addr = %p",copyStr);  
  8. NSLog(@"mcopyStr addr = %p",mcopyStr);  
输出结果如下:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. str addr = 0x8b7a130  
  2. retainStr addr = 0x8b7a130  
  3. copyStr addr = 0x8b751d0  
  4. mcopyStr addr = 0x8b7a170  

分析:

retain仍然和目的对象地址相同;

copy的地址和目的对象地址不相同,是因为源对象是可变的,目的对象不可变,当然需要两个不同的版本;

mutablecopy形成了一个新的副本。因为两个对象的改变会影响到对方,所以需要两个版本。


得到的结论:

1、对于copy来说,如果源对象是不可变的,那么是浅拷贝,没有必要深拷贝;如果源对象可变,为了安全性,深拷贝,生成副本。

2、对于mutablecopy来说,不管源对象是否可变,都是深拷贝。

因此我们在设置property的copy属性时,如果希望对象跟着源对象的值变化,那么就是用retain;如果希望对象保持独立的值,那就使用copy。当然这是在源对象为可变的情况下。


上面讨论的是NSString相关的retain/copy/mutablecopy,在oc里面所有实现了NSCopying和NSMutableCopying协议的类,都具有copy和mutablecopy这两个方法。这里引出了其他的oc对象的copy特性,它们是什么样的,下一篇进行探究。

欢迎指正!  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值