一、拷贝的目的
- 产生一个副本对象;
- 修改了源对象,不会影响副本对象;
- 修改了副本对象,不会影响源对象;
在理解上,可类比Word文档的拷贝
二、如何实现拷贝
ios中用copy和mutableCopy来实现
NSString *str1 = @"123";
NSString *str2 = [str1 copy];
NSMutableString *str3 = [str1 mutableCopy];
NSLog(@"%@,%@,%@",str1,str2,str3);
三、copy和mutableCopy的不同点
- 二者的区别:
copy产生不可变副本;
mutableCopy产生可变副本;
1.验证copy的不可变性
NSString *str1 = @"123";
NSMutableString *str2 = [str1 copy];//此处为验证是否为不可变对象
NSMutableString *str3 = [str1 mutableCopy];
[str2 appendString:@"45"];
[str3 appendString:@"45"];
2.验证mutableCopy的可变性
NSString *str1 = @"123";
NSString *str2 = [str1 copy];
NSMutableString *str3 = [str1 mutableCopy];
[str3 appendString:@"45"];
NSLog(@"%@,%@,%@",str1,str2,str3);
3.从内存地址的角度看
(1)源对象为不可变对象的情况
NSString *str1 = @"123";
NSString *str2 = [str1 copy];
NSMutableString *str3 = [str1 mutableCopy];
NSLog(@"%p,%p,%p",str1,str2,str3);
从内存分布上来看,copy没有产生新的对象,而mutableCopy产生了新的对象并且指针指向了新的内存区域。
在这里不禁怀疑:不是说copy或者mutableCopy都产生新的副本,两者之间互不影响么?
解疑:首先,在这里源对象是不可变的,copy产生的是不可变对象,那么既然新产生的对象也是不可变的,从内存优化的角度来说,也就没有必要产生新的内存区域,直接生成一个新的指针指向原来的不可变对象就OK了;而mutableCopy操作之后得到的是可变对象,那么必然要新生成一个内存空间去存放可变的副本。
(2)源对象为可变对象的情况
NSMutableString *str1 = [NSMutableString stringWithString:@"123"];
NSString *str2 = [str1 copy];
NSMutableString *str3 = [str1 mutableCopy];
NSLog(@"%p,%p,%p",str1,str2,str3);
同理,源对象为可变对象,copy之后为不可变对象,所以内存地址不同;mutableCopy之虽然为可变对象,但是为了达到,副本和源对象互不影响的目的,同样产生了新的内存空间。
四、总结
- 深拷贝:内容拷贝,有产生新对象
- 浅拷贝:指针拷贝,没有产生新对象
NSString *str1 = @"123";
NSString *str2 = [str1 copy]; //浅拷贝
NSMutableString *str3 = [str1 mutableCopy]; //深拷贝
NSLog(@"%p,%p,%p",str1,str2,str3);
0x100001040,0x100001040,0x10062c8c0
NSMutableString *str1 = [NSMutableString stringWithString:@"123"];
NSString *str2 = [str1 copy]; //深拷贝
NSMutableString *str3 = [str1 mutableCopy]; //深拷贝
NSLog(@"%p,%p,%p",str1,str2,str3);
0x10067d480,0xb0dbfc7d66059a9b,0x10067d540
- 所以,不一定copy就是浅拷贝,mutableCopy就是深拷贝,具体情况具体分析。
同样类比NSString,分析出NSdictionary和NSArray也是同样的道理。以下给出表格。
一句话:不可变对象的copy是浅拷贝,剩下的都是深拷贝