字符串的浅拷贝和深拷贝
我们都知道@property修饰字符串时采用关键字copy,那是什么原因的,面试时常问的浅拷贝和深拷贝是什么呢?
- 我们先看一段代码,NSString对象调用copy方法控制台输出的name和str1地址是一样的,说明NSString没有创建新的对象,这种叫做浅拷贝,str2的地址和name的地址不同,通过断点我们知道str2指针其实是NSMutableString类型,调用mutableCopy方法创建了新的对象,返回NSMutableString类型的对象,叫做深拷贝。
NSString *name = @"Billy";
//copy方法浅拷贝
NSString *str1 = [name copy];
//mutableCopy方法深拷贝
NSMutableString *str2 = [name mutableCopy];
NSLog(@"###%p###%p###%p",name,str1,str2);
- 我们在来看NSMutableString类型字符串,NSMutableString对象调用copy方法,是深拷贝,创建一个新的对象,返回的是NSString类型,调用mutableCopy,是深拷贝,创建新的对象,返回NSMutableString类型。
NSMutableString *name = [NSMutableString stringWithString:@"Billy"];
//深拷贝
NSString *str1 = [name copy];
//深拷贝
NSMutableString *str2 = [name mutableCopy];
NSLog(@"###%p###%p###%p",name,str1,str2);
- @property修饰字符串时采用关键字copy,我们定义一个类People,有一个属性name,系统帮我们生成的setter方法其实如下代码
@interface People : NSObject
@property (nonatomic,copy) NSString *name;
@end
@implementation People
-(void)setName:(NSString *)name {
_name = [name copy];
}
@end
- 为什么要使用copy修饰呢,看代码,我们采用NSString给对象的属性赋值时并没有影响
People *p = [[People alloc]init];
NSString *str = @"Billy";
p.name = str;
//修改str不会影响p.name的值,因为修改NSString会创建新的对象
str = @"Jondan";
- 我们采用NSMutableString给对象的属性赋值时,如果不调用copy,修改NSMutableString对象就会修改了属性的值,所以我们要使用copy
People *p = [[People alloc]init];
NSMutableString *str = [NSMutableString stringWithString:@"Billy"];
p.name = str;
//修改str不会影响p.name的值,因为setter里面调用了copy方法实现了深拷贝
//p.name指向的对象和str指向的对象不是同一个对象
[str appendString:@"Jondan"];
6.重新给大家进行补充,People类有个属性brief
//用可变字符串赋值给不可变字符串
People *p = [[People alloc] init];
NSMutableString *str = [NSMutableString stringWithString:@"Hello!"];
p.brief = str;
[str appendString:@"ee"];
NSLog(@"%p\n%p\n%@\n%@\n",str,p.brief,str,p.brief);
//打印结果0x10076d3c0,0x10076d3c0,Hello!ee,Hello!ee
这种情况就一定要用copy来修饰,因为是用可变字符串给不可变字符串赋值,如果使用了strong来修饰,setter方法里不会调用copy方法,就不会创建新的对象,修改str就会修改了brief的值。
7.NSString用copy和strong的区别呢,如果给属性赋值时用不可变字符串给不可变字符串赋值,这种情况的话copy和strong都是一样的,OC中 NSString 为不可变字符串的时候,用 copy 和 strong 都是只分配一次内存,但是如果用 copy 的时候,需要先判断字符串是否是不可变字符串,如果是不可变字符串,就配空间,如果是可变字符串才分配空间。如果程序中用到 NSstring 的地方特别多,每都要先进行判断就会耗耗费性能,影响用户体验,用 strong 就不会再进行判断,所以,不可变字符串可以直接用 strong修饰。
People *p = [[People alloc] init];
NSString *string = @"Hello!";
p.brief = str;