概念
-
浅拷贝:指针拷贝,复制一个新的指针,指向同一块内存区域。即复制的对象和原对象都指向同一个内存
-
深拷贝:内容拷贝,拷贝数据到一块新内存区域,指针指向新拷贝的内存。
非容器不可变对象/可变对象:NSString/ NSMutableString等
容器不可变对象/可变对象:NSArray/NSMutableArray等
先说说Strong修饰的变量
@interface Copy()
@property (nonatomic,strong)NSMutableString *strongStringA;
@property (nonatomic,strong)NSMutableString *strongStringB;
@end
@implementation Copy
-(void)strongStringCopy{
NSMutableString *string = [NSMutableString stringWithFormat:@"name"];
NSLog(@"原始NSMutableString的地址:%p",string);
self.strongStringA=string;
NSLog(@"对strongStringA赋值后的地址:%p",self.strongStringA);
[string appendString:@" is kindom_0129"];
NSLog(@"原始值修改后的地址:%p 值:%@",string,string);
NSLog(@"对原始值修改后strongStringA的地址:%p 值:%@",self.strongStringA,self.strongStringA);
}
@end
打印结果:
原始NSMutableString的地址:0x6000018a57d0
对strongStringA赋值后的地址:0x6000018a57d0
原始值修改后的地址:0x6000018a57d0 值:name is kindom_0129
对原始值修改后strongStringA的地址:0x6000018a57d0 值:name is kindom_0129
- 结论:
A使用属性对可变字符串做出了appendstring这样的操作,B中的值也会发生修改。
strong: 为浅拷贝,也就是指针引用
非容器不可变对象NSString
NSString *string = [NSString stringWithFormat:@"name"];
NSLog(@"原始string的地址:%p",string);
NSString *copyString = [string copy];
NSLog(@"拷贝string的地址:%p",copyString);
NSMutableString *copyStringB = [string mutableCopy];
NSLog(@"深拷贝string的地址:%p",copyStringB);
[copyStringB appendString:@"id kindom_0129"];
NSLog(@"深拷贝string的值:%@",copyStringB);
打印结果:
原始string的地址:0xe44d9dca7936d694
拷贝string的地址:0xe44d9dca7936d694
深拷贝string的地址:0x600003ed1260
深拷贝string的值:nameid kindom_0129
可以看出copy时对象的地址与原来的相同,而mutableCopy地址改变了,并且能够对其进行修改
结论:
1.对于非容器不可变对象的copy为浅拷贝,mutableCopy为深拷贝
2.浅拷贝获得的对象地址和原对象地址一致, 返回的对象为不可变对象
3.深拷贝返回新的内存地址,返回对象为可变对象
非容器可变对象NSMutableString
首先看下面这段代码:
-(void)copyString{
NSMutableString *string = [NSMutableString stringWithFormat:@"name"];
NSLog(@"原始string的地址:%p",string);
NSMutableString *copyString = [string copy];
NSLog(@"拷贝string的地址:%p",copyString);
[copyString appendString:@"test"];
}
结果呢?
看到了吗?居然crash了,为什么呢。我们细看下:
我们的MutableString对象调用了copy之后,拷贝出来的字符串内存地址发生了变化,也就是说这里是发生了深拷贝。
接着我们使用copyString调用appendString方法发生了很常规的闪退,日志显示我们拷贝出来的是NSTaggedPointerString,这是个不可变字符串。
也就是说可变字符串在copy之后会发生深拷贝,拷贝出来的是一个不可变字符串!
再来看看下面这段代码:
-(void)copyString{
NSMutableString *string = [NSMutableString stringWithFormat:@"name"];
NSLog(@"原始string的地址:%p",string);
NSMutableString *copyString = [string copy];
NSLog(@"拷贝string的地址:%p",copyString);
NSMutableString *copyStringB = [string mutableCopy];
NSLog(@"深拷贝string的地址:%p",copyStringB);
[copyStringB appendString:@"id kindom_0129"];
NSLog(@"深拷贝string的值:%@",copyStringB);
}
结果:
原始string的地址:0x60000140f9f0
拷贝string的地址:0xd62b10f4fd1f50c5
深拷贝string的地址:0x60000147a310
深拷贝string的值:nameid kindom_0129
结论:
1.对于非容器可变对象的copy为深拷贝
2.mutableCopy为深拷贝,并且可以修改
3.可变字符串在copy之后会发生深拷贝,拷贝出来的是一个不可变字符串!
容器不可变对象:NSArray等
先来看看下面的代码:
NSMutableString *str1 = [NSMutableString stringWithFormat:@"非容器可变对象"];
NSArray *array = [NSArray arrayWithObjects:str1, @"非容器不可变对象", nil];
NSArray *copyArray = [array copy];
NSArray *mutableCopyArray = [array mutableCopy];
NSLog(@"array_p: %p, class: %@", array, [array class]);
NSLog(@"copyArray_p: %p, class: %@", copyArray, [copyArray class]);
NSLog(@"mutableCopyArray_p: %p, class: %@", mutableCopyArray, [mutableCopyArray class]);
NSLog(@"======原对象=====");
NSLog(@"object_p: %p, class: %@", array[0], [array[0] class]);
NSLog(@"object_p: %p, class: %@", array[1], [array[1] class]);
NSLog(@"======copy对象=====");
NSLog(@"object_p: %p, class: %@", copyArray[0], [copyArray[0] class]);
NSLog(@"object_p: %p, class: %@", copyArray[1], [copyArray[1] class]);
NSLog(@"======mutableCopy对象=====");
NSLog(@"object_p: %p, class: %@", mutableCopyArray[0], [mutableCopyArray[0] class]);
NSLog(@"object_p: %p, class: %@", mutableCopyArray[1], [mutableCopyArray[1] class]);
结果:
array_p: 0x6000005cca80, class: __NSArrayI
copyArray_p: 0x6000005cca80, class: __NSArrayI
mutableCopyArray_p: 0x600000bd03c0, class: __NSArrayM
======原对象=====
object_p: 0x600000bd00c0, class: __NSCFString
object_p: 0x10b5211e0, class: __NSCFConstantString
======copy对象=====
object_p: 0x600000bd00c0, class: __NSCFString
object_p: 0x10b5211e0, class: __NSCFConstantString
======mutableCopy对象=====
object_p: 0x600000bd00c0, class: __NSCFString
object_p: 0x10b5211e0, class: __NSCFConstantString
结论:
1.copy为浅拷贝;
2.mutableCopy为深拷贝;
3.无论是浅拷贝还是深拷贝,容器内的元素仍然是浅拷贝。
容器可变对象:NSMutableArray等
代码:
NSMutableString *str1 = [NSMutableString stringWithFormat:@"非容器可变对象"];
NSMutableArray *array = [NSMutableArray arrayWithObjects:str1, @"非容器不可变对象", nil];
NSMutableArray *copyArray = [array copy];
NSMutableArray *mutableCopyArray = [array mutableCopy];
NSLog(@"array_p: %p, class: %@", array, [array class]);
NSLog(@"copyArray_p: %p, class: %@", copyArray, [copyArray class]);
NSLog(@"mutableCopyArray_p: %p, class: %@", mutableCopyArray, [mutableCopyArray class]);
NSLog(@"======原对象=====");
NSLog(@"object_p: %p, class: %@", array[0], [array[0] class]);
NSLog(@"object_p: %p, class: %@", array[1], [array[1] class]);
NSLog(@"======copy对象=====");
NSLog(@"object_p: %p, class: %@", copyArray[0], [copyArray[0] class]);
NSLog(@"object_p: %p, class: %@", copyArray[1], [copyArray[1] class]);
NSLog(@"======mutableCopy对象=====");
NSLog(@"object_p: %p, class: %@", mutableCopyArray[0], [mutableCopyArray[0] class]);
NSLog(@"object_p: %p, class: %@", mutableCopyArray[1], [mutableCopyArray[1] class]);
结果:
array_p: 0x6000029f1c50, class: __NSArrayM
copyArray_p: 0x6000027aab80, class: __NSArrayI
mutableCopyArray_p: 0x6000029f19b0, class: __NSArrayM
======原对象=====
object_p: 0x6000029f1b00, class: __NSCFString
object_p: 0x10bdb11e0, class: __NSCFConstantString
======copy对象=====
object_p: 0x6000029f1b00, class: __NSCFString
object_p: 0x10bdb11e0, class: __NSCFConstantString
======mutableCopy对象=====
object_p: 0x6000029f1b00, class: __NSCFString
object_p: 0x10bdb11e0, class: __NSCFConstantString
我们再添加一行代码:
[copyArray addObject:@"dddd"];
此时运行发现crash了:
结论:
1.容器类可变对象mutableCopy和copy都返回一个新的容器,
2.容器内的元素仍然是浅拷贝
3.容器类可变对象copy后生成的新对象为不可变对象,这与非容器类可变对象copy后是一样的
***总结:
1.copy并不一定是浅拷贝,如果被拷贝的对象是可变数组或者字符串,这时候会发生深拷贝,反之则是浅拷贝。
2.copy出来的一定是不可变对象
3.对于容器对象,无论是浅拷贝还是深拷贝,容器内的内容都是浅拷贝
4.对于可变对象的深拷贝mutableCopy可以修改