深拷贝就是把内容拷贝一份,生成一个新的对象,新对象计数器为1, 源对象计数器不变。
浅拷贝就是指针拷贝,把地址拷贝出来一份(副本),副本和源地址指向同一个对象,源对象计数器加1,源对象和副本的计数器相同。
OC中存在copy和mutablecopy两种拷贝函数,只要调用了copy不管是NSString,NSDictionary、NSArray还是NSMutableString、NSMutableDictionary、NSMutableArray拷贝出来的都是不可变的副本。
当调用mutablecopy时,拷贝出来的都是可变的副本。可变对象或者不可变对象mutablecopy都产生一个新的对象,引用计数为1,源对象的计数不变。
OC设置copy语法本事就是为了改变副本而不去影响源对象,所以既然copy出来的都不可变,自然也不会产生一个新的对象,相当于对源对象进行了retain操作。可变对象进行copy操作,可变对象变成了不可变对象,结构上发生了改变,所以说就是深拷贝。
总的来说就是:不可变对象的copy操作是浅拷贝,其他操作都是深拷贝。
可变对象的copy和mutalbecopy方法都是深拷贝,而且都是单层拷贝。举例说明一下,数组a和数组b,让数组b = [a copy] 或者 b = [a mutableCopy],虽然b的地址和a的地址不同,但是里面的数组元素的地址和源数组里面的对象的地址还是相同的,也就是说数组内容还是指向原数组里面的元素的。
copy和strong修饰变量的区别
先看一段代码运行的结果,声明两个属性:
@property (nonatomic, strong) NSString *rStr;
@property (nonatomic, copy) NSString *cStr;- (void)viewDidLoad {
[super viewDidLoad];
NSMutableString *mStr = [NSMutableString stringWithFormat:@"abc"];
self.rStr = mStr;
self.cStr = mStr;
NSLog(@"mStr:%@, =%p, =%p",mStr, mStr, &mStr);
NSLog(@"rStr:%@, =%p, =%p",_rStr, _rStr, &_rStr);
NSLog(@"cStr:%@, =%p, =%p",_cStr, _cStr, &_cStr);
}假设,mStr对象的地址是0x123,也就是说字符串abc的首地址是0x123,mStr变量自身在内存中的地址为0x789;
当执行完mStr赋值给strong(retain)的rStr时,rStr对象的地址是0x123,rStr变量自身在内存中的地址是0x345,rStr和mStr指向同样的地址,他们指向的是同一个对象abc;
当执行完mStr赋值给copy的cStr时,cStr对象的地址是0x258,cStr变量自身在内存中的地址是0x434,cStr和mStr指向的地址是不一样的,他们指向的是不同的对象。
在执行下面一句代码:
[mStr appendString:@"de"];
结果,
使用strong的字符串rStr的值:@"abcde",
使用copy的字符串cStr的值:@"abc"
所以,当把NSMutableString赋值给NSString的时候,如果希望字符串的值跟着赋值的字符串值变化,可以使用strong、retain。strong或retain仅仅是指针引用,增加了引用计数,所以当源字符串改变的时候,它也会跟着改变(浅拷贝)。而copy声明的变量,不会跟着改变,是深拷贝。
如果赋值是NSString对象,那么使用copy还是strong或者retain,结果是一样的。
简单描述一下用strong和weak来修饰成员变量的对比:
用weak修饰,初始化之后就会被释放掉,具体可参考下面链接blog.csdn.net/aaaaazq/art…