在工作中如果不能正确理解浅拷贝与深拷贝就会造成不想改变的值被改变了,出现了再次使用数组时没有数据,显示的值不是我们想要的等一些问题。只有真正理解了浅拷贝与深拷贝才能使我们在开发中事半功倍,废话少说,代码走起~~~
定义理解
浅拷贝:拷贝后只是指向了该对象的地址,这两个对象指向了同一个内存地址,通过任何一个对象修改值,这两个对象再次获取值都是获取修改后的值。
深拷贝:拷贝了对象的内容然后重新开辟了新的内存空间,这是两个互相独立的对象,对任意一个修改值,另一个的值都不会改变。
字符串的深拷贝与浅拷贝
不可变字符串
NSString *test = @"copy456";
NSString *test1 = [test copy]; //浅拷贝
NSString *test2 = [test mutableCopy]; //深拷贝
打印结果:
test:0x101683068
test1:0x101683068
test2:0x604000049330
从打印结果我们可以看到使用copy赋值给一个不可变对象时是浅拷贝,指向了同一个内存地址。使用mutableCopy赋值给一个不可变对象是深拷贝,重新分配了内存空间。
可变字符串
NSMutableString *mtest = [[NSMutableString alloc] initWithString:@"mutableCopy NSSting"];
NSMutableString *mtest4 = [mtest copy]; // 深拷贝
NSMutableString *mtest5 = [mtest mutableCopy]; //深拷贝
打印结果:
mtest:0x600000445ac0
mtest4:0x600000445c10
mtest5:0x600000445a90
通过copy或mutableCopy的方式赋值给可变对象,从打印的结果可以看到它们三个指向的内存地址都是不一样的,因此都是深拷贝。
集合类对象的深拷贝与浅拷贝
对于集合类对象我们以数组为例进行说明
不可变对象
NSArray *testArray = @[@"A", @"B", @"C"];
NSArray *testArray1 = [testArray copy]; //浅拷贝
NSArray *testArray2 = [testArray mutableCopy]; //深拷贝
打印结果:
testArray:0x60400004a4d0
testArray1:0x60400004a4d0
testArray2:0x60400004a770
通过copy赋值testArray1与testArray指向相同的内存地址,因此通过copy的方式赋值给不可变对象是浅拷贝。testArray2是新的内存地址,通过mutableCopy的方式赋值给一个不可变对象是深拷贝。
可变对象
NSMutableArray *mTestArray = [[NSMutableArray alloc] init];
NSMutableArray *mTestArray1 = [mTestArray copy]; //深拷贝
NSMutableArray *mTestArray2 = [mTestArray mutableCopy]; //浅拷贝
打印结果:
testArray:0x60800005ba50
testArray1:0x60c000004910
testArray2:0x60800005bc00
无论是copy还是mutableCopy赋值给一个可变对象时都是深拷贝。
集合对象的值
打印数组的第一个值的内存地址
NSLog(@"testArray 1value:%p", [mTestArray objectAtIndex:0]);
NSLog(@"testArray1 1value:%p", [mTestArray1 objectAtIndex:0]);
NSLog(@"testArray2 1value:%p", [mTestArray2 objectAtIndex:0]);
打印结果:
testArray 1value:0x104b67238
testArray1 1value:0x104b67238
testArray2 1value:0x104b67238
我们看到打印的结果第一个值都指向了同一个内存地址,这说明集合对象的深拷贝只是单层深拷贝,只是给该对象分配了一个新的内存地址而集合对象里面的值还都指向原来的内存地址。
property中使用copy属性
@interface ViewController ()
@property (nonatomic, copy) NSString *pTest;
@property (nonatomic, copy) NSMutableString *mpTest;
@end
self.pTest = test;
NSLog(@"test:%p", test);
NSLog(@"pTest:%p", _pTest);
self.mpTest = mtest;
NSLog(@"mtest:%p", mtest);
NSLog(@"mpTest:%p", _mpTest);
打印结果:
test:0x10b07e088
pTest:0x10b07e088
mtest:0x6040002410e0
mpTest:0x604000241770
通过打印结果我们可以看到不可变对象是浅拷贝,可变度对象是深拷贝。其实看到set方法的实现原来我们就明白了property里的copy什么时候是深拷贝,什么时候是浅拷贝
- (void)setPTest:(NSString *)pTest {
_pTest = [pTest copy];
}
网友评论