iOS中的深拷贝和浅拷贝

浅拷贝又叫做指针拷贝,比如说有一个指针,这个指针指向一个字符串,也就是说这个指针变量的值是这个字符串的地址,那么此时对这个字符串进行指针拷贝意思就是又创建了一个指针变量,这个指针变量的值是这个字符串的地址,也就是这个字符串的引用计数+1。

深拷贝又叫做内容拷贝,比如有一个指针,这个指针指向一个字符串,也就是说这个指针变量的值是这个字符串的地址值,那么此时对这个字符春进行内容拷贝,就会创建一个新的指针,在一个新的地址区域创建一个字符串,这个字符串的值和原字符串的值相同,新的指针指向这个新创建的字符串。这时原字符串的引用计数没有+1。

不管是集合对象还是非集合对象,接收到copy和mutableCopy消息时,都遵循以下准则:

    copy返回immutable对象

    mutableCopy返回mutable对象

不可变的对象NSString,NSArray,NSDictionary等,copy方法进行了浅拷贝,mutableCopy方法进行了深拷贝。

可变对象NSMutableString,NSMutableArray等,copy方法进行了深拷贝生成一个不可变对象,mutableCopy方法进行深拷贝生成一个可变对象。

面试题:为什么NSString类型的成员变量的修饰属性用copy而不是strong呢?

首先要搞清楚的就是对NSString类型的成员变量用copy修饰和用strong修饰的区别。如果使用了copy修饰符,那么在给成员变量赋值的时候就会对被赋值的对象进行copy操作,然后再赋值给成员变量。如果使用的是strong修饰符,则不会执行copy操作,直接将被赋值的变量赋值给成员变量。

假设有一个NSString类型的成员变量string,对其进行赋值:

NSString*testString =@"test";

self.string = testString;

如果该成员变量是用copy修饰的,则等价于:

self.string = [testStringcopy];

如果是用strong修饰的,则没有copy操作:

self.string= testString;

知道了使用copy和strong的区别后,我们再来分析为什么要使用copy修饰符。先看一段代码:

NSMutableString*mutableString = [[NSMutableStringalloc] initWithString:@"test"];

self.string = mutableString;

NSLog(@"%@",self.string);

[mutableString appendString:@"addstring"];

NSLog(@"%@",self.string);

如果这里成员变量string是用strong修饰的话,打印结果就是:

2018-09-0410:50:16.909998+0800copytest[2856:78171]test

2018-09-0410:50:16.910128+0800copytest[2856:78171]testaddstring

很显然,当mutableString的值发生了改变后,string的值也随之发生改变,因为self.string = mutableString;这行代码实际上是执行了一次指针拷贝。string的值随mutableString的值的发生改变这显然不是我们想要的结果。

如果成员变量string是用copy修饰,打印结果就是:

2018-09-0410:58:07.705373+0800copytest[3024:84066]test

2018-09-0410:58:07.705496+0800copytest[3024:84066]test

这是因为使用copy修饰符后,self.string = mutableString;就等价于self.string = [mutableString copy];,也就是进行了一次深拷贝,所以mutableString的值再发生变化就不会影响到string的值。

回答面试题:

NSString类型的成员变量使用copy修饰而不是strong修饰是因为有时候赋给该成员变量的值是NSMutableString类型的,这时候如果修饰符是strong,那成员变量的值就会随着被赋值对象的值的变化而变化。若是用copy修饰,则对NSMutableString类型的值进行了一次深拷贝,成员变量的值就不会随着被赋值对象的值的改变而改变。

你可能感兴趣的:(iOS中的深拷贝和浅拷贝)