浅谈深浅复制,retain与copy的区别(摘抄)
2017-03-28 19:45
387 查看
在iOS开发中我们一般都这么定义:@property (nonatomic,copy)
NSString *name,而不这么定义:@property (nonatomic,retain) NSString *name,两者的差别就在一个使用copy,一个使用retain。
一直以来都不明白为什么,今天通过查阅资料总算弄明白了,所以记录一下。
在说明白retain和copy的区别,首先需要明白深复制和浅复制的概念。
1 深复制:内容拷贝,源对象和副本对象指的是两个不同的对象,源对象引用计数器不变,副本对象引用计数器为1
2 浅复制:指针拷贝,源对象和副本对象指的都是同一个对象,对象引用计数器+1,相当于retain
只有不可变对象创建不可变副本(copy)才是浅复制,其它的都是深复制
上面的结论至关重要,大家可以对NSString和NSMutableString分别测试,在此不再赘述。
下面通过实验来说明copy和retain的区别。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
先执行test,再执行test2,两次执行的结果如下:
![](https://img-blog.csdn.net/20151209193606057)
![](https://img-blog.csdn.net/20151209193635805)
下面来分析一下:
(1)在test中,str指向一个不可变的NSString对象,地址为0x9d040,然后str分别给name和name2赋值,由于name和name2都是NSString对象,所有都属于浅复制,赋值后都是指向str对象地址0x9d040,所有打印结果三者指向同一个对象。
(2)在test2中,str指向一个可变的NSMutableString对象,地址为0x7c140e60,然后分别给name和name2赋值,此时copy对应的name是深复制,所以会复制出另一个对象,地址为0x7c148b80。而retain对应的name2依然指向str对象地址0x7c140e60,所以打印结果是str和name2对应同一地址,name对应另一个地址。
所以得出结论:
(1)copy是创建一个新对象,两个对象内容相同,旧对象没有变化。新的对象retain为1,与旧有对象的引用计数不变。旧对象发生改变不影响新对象,copy减少对象对上下文的依赖。
(2)retain属性表示两个对象地址相同(建立一个指针,指针拷贝),内容相同,这个对象的retain值+1。两个对象要改变就一起改变。
(3)如果把一个对象赋值给另一个对象(如上面把str赋值给name或name2),如果该对象是不可变的,那么另一个对象是copy或者retain都可以,没区别;把一个对象赋值给另一个对象,如果该对象是可变的,并且希望另一个对象随着该对象变化而变化,则可以把另一个对象设置为retain(如上面把str赋值给name2);如果希望另一个对象不随着该对象变化而变化,则可以把另一个对象设置为copy(如上面把str赋值给name)。
顶0
NSString *name,而不这么定义:@property (nonatomic,retain) NSString *name,两者的差别就在一个使用copy,一个使用retain。
一直以来都不明白为什么,今天通过查阅资料总算弄明白了,所以记录一下。
在说明白retain和copy的区别,首先需要明白深复制和浅复制的概念。
1 深复制:内容拷贝,源对象和副本对象指的是两个不同的对象,源对象引用计数器不变,副本对象引用计数器为1
2 浅复制:指针拷贝,源对象和副本对象指的都是同一个对象,对象引用计数器+1,相当于retain
只有不可变对象创建不可变副本(copy)才是浅复制,其它的都是深复制
上面的结论至关重要,大家可以对NSString和NSMutableString分别测试,在此不再赘述。
下面通过实验来说明copy和retain的区别。
@interface ViewController () @property (nonatomic,copy) NSString *name; @property (nonatomic,retain) NSString *name2; @end -(void)test{ NSString *str = @"fffff"; self.name = str; self.name2 = str; NSLog(@" str: %p",str); NSLog(@" copy: %p",self.name); NSLog(@"retain: %p",self.name2); } -(void)test2{ NSMutableString *str = [NSMutableString stringWithString:@"ffffff"]; self.name = str; self.name2 = str; NSLog(@" strM: %p",str); NSLog(@" copy: %p",self.name); NSLog(@"retaini: %p",self.name2); }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
先执行test,再执行test2,两次执行的结果如下:
下面来分析一下:
(1)在test中,str指向一个不可变的NSString对象,地址为0x9d040,然后str分别给name和name2赋值,由于name和name2都是NSString对象,所有都属于浅复制,赋值后都是指向str对象地址0x9d040,所有打印结果三者指向同一个对象。
(2)在test2中,str指向一个可变的NSMutableString对象,地址为0x7c140e60,然后分别给name和name2赋值,此时copy对应的name是深复制,所以会复制出另一个对象,地址为0x7c148b80。而retain对应的name2依然指向str对象地址0x7c140e60,所以打印结果是str和name2对应同一地址,name对应另一个地址。
所以得出结论:
(1)copy是创建一个新对象,两个对象内容相同,旧对象没有变化。新的对象retain为1,与旧有对象的引用计数不变。旧对象发生改变不影响新对象,copy减少对象对上下文的依赖。
(2)retain属性表示两个对象地址相同(建立一个指针,指针拷贝),内容相同,这个对象的retain值+1。两个对象要改变就一起改变。
(3)如果把一个对象赋值给另一个对象(如上面把str赋值给name或name2),如果该对象是不可变的,那么另一个对象是copy或者retain都可以,没区别;把一个对象赋值给另一个对象,如果该对象是可变的,并且希望另一个对象随着该对象变化而变化,则可以把另一个对象设置为retain(如上面把str赋值给name2);如果希望另一个对象不随着该对象变化而变化,则可以把另一个对象设置为copy(如上面把str赋值给name)。
顶0
相关文章推荐
- 详谈OC(object-c)深浅复制/拷贝-什么情况下用retain和copy
- 详谈OC(object-c)深浅复制/拷贝-什么情况下用retain和copy
- 详谈OC(object-c)深浅复制/拷贝-什么情况下用retain和copy
- 详谈OC(object-c)深浅复制/拷贝-什么情况下用retain和copy
- 详谈OC(object-c)深浅复制/拷贝-什么情况下用retain和copy
- 73.assign/retain/copy及深浅拷贝的区别
- IOS-10-详谈OC(object-c)深浅复制/拷贝-什么情况下用retain和copy,mutableCopy
- 详谈OC(object-c)深浅复制/拷贝-什么情况下用retain和copy
- 详谈OC(object-c)深浅复制/拷贝-什么情况下用retain和copy
- 属性项目的定义(property)copy&retain的区别
- nonatomic,assign,copy,retain的区别
- retain和copy的区别 #import @class 的区别
- nonatomic retain copy assign区别
- retain和copy还有assign的区别
- retain和copy还有assign的区别
- [转]Object-C属性标签assign,retain,copy区别
- IOS atomic与nonatomic,assign,copy与retain的定义和区别
- retain和copy的区别
- object c 中 retain 和copy的区别
- nonatomic,assign,copy,retain的区别(转)