iOS中深复制和浅复制问题
来源:互联网 发布:mac 查找文件路径 编辑:程序博客网 时间:2024/06/05 14:09
NSDictionary对象,添加内容,然后通过代码产生可变和不可变副本,这些复制是深复制还是浅复制?那么对于可变对象呢?为什么NSString定义属性时需要用copy呢?copy属性和copy对象有什么不同?
首先先说一下copy和retain的区别:
copy是创建一个新对象,是内容拷贝。retain是创建一个指针,引用对象计数加1。retain属性表示两个对象地址相同(建立一个指针,指针拷贝),内容当然相同,这个对象的retain值+1。
对于深复制和浅复制我们来看下面的代码:
NSDictionary *dict = [NSDictionarydictionaryWithObjectsAndKeys:@"1",@"1",@"2",@"2",nil];
NSLog(@"原字典:%p",dict);
NSDictionary *dictRetain = dict.retain;
NSLog(@"计数器:%p",dictRetain);
NSDictionary *dictCopy = dict.copy;
NSLog(@"浅复制:%p",dictCopy);
NSMutableDictionary *dictMutableCopy = dict.mutableCopy;
NSLog(@"深复制:%p",dictMutableCopy);
打印结果:
计数器:0x7f7f89d21ec0
浅复制:0x7f7f89d21ec0
深复制:0x7f7f89c09680
也就是说,对于retain和copy产生的字典内存与原地址内存相同,也就是说copy产生的不可变版本是浅复制和retain一样拷贝的是指针。而mutableCopy深复制是拷贝的对象内容。
下面我们看一个可变对象的拷贝过程:
NSMutableString *string = [NSMutableStringstringWithString:@"name"];
NSLog(@"strP:%p",string);
NSString *stringCopy = [stringcopy];
NSLog(@"copy:%p",stringCopy);
NSMutableString *mStringCopy = [stringcopy];
NSLog(@"copy:%p",mStringCopy);
NSMutableString *stringMCopy = [stringmutableCopy];
NSLog(@"mCopy:%p",stringMCopy);
打印结果:
strP:0x7faea1f124d0
copy:0xa000000656d616e4
copy:0xa000000656d616e4
mCopy:0x7faea1e0df20
对于可变对象进行复制,结果和上面不一样了。
我们可以这样理解:如果对一不可变对象复制,copy是指针复制(浅拷贝)和mutableCopy就是对象复制(深拷贝)。如果是对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的。
还有一个问题就是:我们知道,在@property属性里copy说的是复制了一个新的对象,引用计数不加1.那么这里属性copy则是使用了深复制。而调用copy方法则是做了一个浅复制。
这也就是为什么NSString属性变量要用copy关键字。如果把一个NSString赋值给NSMutableString属性时,如果使用了strong,则相当于浅复制。两个指针指向同一块内存,当NSMutableString改变后,NSString也就改变了。如果使用了copy,则是深复制。两个对象存在于不同的内存中,当NSMutableString改变时,不影响NSString.
另外,对于字符串来说,我们在使用的时候还要注意:
initWithFormat会创建新空间,initWithString不一定创建新空间,取决于参数。如果后面是常量字符串则不会创建新空间,如果是定义新字符串,则会创建新空间。下面是测试代码:
NSString *name = [[NSString alloc]initWithFormat:@"张三"];
NSString *name = [[NSStringalloc]initWithString:@"张三"];
NSLog(@"%ld",[nameretainCount]);
[name retain];
NSLog(@"%ld",[nameretainCount]);
[name copy];
NSLog(@"%ld",[nameretainCount]);
[name mutableCopy];
NSLog(@"%ld",[nameretainCount])
结果:如果是initWithString,则输入结果全为-1,如果是initWithFormat,结果分别是:1,2,3,4
- iOS中深复制和浅复制问题
- iOS深复制和浅复制
- iOS - 深复制和浅复制
- Java中浅复制和深复制
- Java中深复制和浅复制
- iOS深复制浅复制
- ios的浅复制和深复制 (NSCoping协议)
- iOS学习之——浅复制和深复制
- iOS - 深复制浅复制和c数组的关系
- 浅谈iOS开发中的浅复制和深复制
- iOS开发之深复制和浅复制
- 深复制和浅复制
- 深复制和浅复制
- 深复制和浅复制
- 深复制和浅复制
- 深复制和浅复制
- 深复制和浅复制
- 深复制和浅复制
- javascript内置对象------event对象
- 营销短信API专用通道
- pros & cons of Meson,CMake, Autotools and Tup
- Android图片加载框架Picasso使用教程 (五)
- 贪心算法入门
- iOS中深复制和浅复制问题
- Javascript Math ceil()、floor()、round()三个函数的区别
- 【NAS】NFS协议介绍
- Spring学习总结(15)——Spring AOP 拦截器的基本实现
- 最小割总结
- VI 编辑器
- Android mediaplayer 播放本地音乐文件
- JSON 解析遇到的坑
- iOS--错误集锦--svn提交出错 an error occurred and the operation could not be completed