copy 与 retain的区别,以及copy与mutablecopy的区别
2016-03-02 18:31
363 查看
copy 与 retain的区别
copy: 建立一个索引计数为1的对象,然后释放旧对象retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1
Copy其实是建立了一个相同的对象,而retain不是:比如一个NSString对象,地址为0×1111,内容为@”STR”,
Copy到另外一个NSString之 后,地址为0×2222,内容相同,新的对象retain为1, 旧有对象没有变化
而retain到另外一个NSString之 后,地址相同(建立一个指针,指针拷贝),内容当然相同,这个对象的retain值+1
也就是说,retain是指针拷贝,copy是内容拷贝。
深拷贝与浅拷贝(mutableCopy与Copy)的区别
ios中并不是所有的对象都支持copy,mutableCopy,遵守NSCopying 协议的类可以发送copy消息,遵守NSMutableCopying 协议的类才可以发送mutableCopy消息。假如发送了一个没有遵守上诉两协议而发送 copy或者 mutableCopy,那么就会发生异常。但是默认的ios类并没有遵守这两个协议。如果想自定义一下copy 那么就必须遵守NSCopying,并且实现 copyWithZone: 方法,如果想自定义一下mutableCopy 那么就必须遵守NSMutableCopying,并且实现 mutableCopyWithZone: 方法。ios提供了copy和mutablecopy方法,顾名思义,copy就是复制了一个imutable的对象,而mutablecopy就是复制了一个mutable的对象。以下将举几个例子来说明。
1. 系统的非容器类对象
这里指的是NSString,NSNumber等等一类的对象。
NSString *string = @"origion";
NSString *stringCopy = [string copy];
NSMutableString *stringMCopy = [string mutableCopy];
[stringMCopy appendString:@"!!"];
查看内存可以发现,string和stringCopy指向的是同一块内存区域(又叫apple弱引用weak reference),此时stringCopy的引用计数和string的一样都为2(这里需要注意一下,因为@"origion"对象是常量数据段,不是堆上的对象,所以string与stringCopy实际都是指向一个非堆上的对象,他们的引用计数应该是-1,可以通过程序验证。我们所说的引用计数实际上是用于管理堆上申请的对象。)。而stringMCopy则是我们所说的真正意义上的复制,系统为其分配了新内存,但指针所指向的字符串还是和string所指的一样。
再看下面的例子:
NSMutableString *string = [NSMutableString stringWithString: @"origion"];
NSString *stringCopy = [string copy];
NSMutableString *mStringCopy = [string copy];
NSMutableString *stringMCopy = [string mutableCopy];
[mStringCopy appendString:@"mm"];//error
[string appendString:@" origion!"];
[stringMCopy appendString:@"!!"];
以上四个NSString对象所分配的内存都是不一样的。但是对于mStringCopy其实是个imutable对象,所以上述会报错。
对于系统的非容器类对象,我们可以认为,如果对一不可变对象复制,copy是指针复制(浅拷贝)和mutableCopy就是对象复制(深拷贝)。如果是对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的。
相关文章推荐
- INSTALL_FAILED_NO_MATCHING_ABIS 的解决办法
- Troubleshooting: 'Log file sync' Waits
- ADB server didn't ACK,failed to start daemon的解决方法
- 检查Email格式是否合法的正则表达式
- 《Pedestrain detection in Infrared Images》
- 解决 VC2012 ATL 多线程调用 报错:E_UNEXPECTED Catastrophic failure.
- 理解assign,copy,retain
- sqoop连接mysql出现Failed to list databases com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
- 76.You need to display the first names of all customers from the CUSTOMERS table that contain the
- pod的SDK报错,Linker command failed with exit code1(use -v to see invocation)
- pod的SDK报错,Linker command failed with exit code1(use -v to see invocation)
- AIX 6.1 异步 I/O 的 配置与性能评估
- 使用RAID进行磁盘管理
- AIX 6.1 异步 I/O 的 配置与性能评估
- studio中install_failed_dexopt 解决
- 环信SDK报错处理方法obtain an updated library from the vendor, or disable bitcode for this target. for archit
- 环信SDK报错处理方法obtain an updated library from the vendor, or disable bitcode for this target. for archit
- Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift 论文翻译
- io.h头文件下的一些函数 http://blog.csdn.net/babygjx/article/details/5740038
- 设计模式 ( 十二 ) 职责链模式(Chain of Responsibility)(对象行为)