在工作中如果不能正確理解淺拷貝與深拷貝就會(huì)造成不想改變的值被改變了,出現(xiàn)了再次使用數(shù)組時(shí)沒有數(shù)據(jù),顯示的值不是我們想要的等一些問題。只有真正理解了淺拷貝與深拷貝才能使我們?cè)陂_發(fā)中事半功倍,廢話少說,代碼走起~~~
定義理解
淺拷貝:拷貝后只是指向了該對(duì)象的地址,這兩個(gè)對(duì)象指向了同一個(gè)內(nèi)存地址,通過任何一個(gè)對(duì)象修改值,這兩個(gè)對(duì)象再次獲取值都是獲取修改后的值。
深拷貝:拷貝了對(duì)象的內(nèi)容然后重新開辟了新的內(nèi)存空間,這是兩個(gè)互相獨(dú)立的對(duì)象,對(duì)任意一個(gè)修改值,另一個(gè)的值都不會(huì)改變。
字符串的深拷貝與淺拷貝
不可變字符串
NSString *test = @"copy456";
NSString *test1 = [test copy]; //淺拷貝
NSString *test2 = [test mutableCopy]; //深拷貝
打印結(jié)果:
test:0x101683068
test1:0x101683068
test2:0x604000049330
從打印結(jié)果我們可以看到使用copy賦值給一個(gè)不可變對(duì)象時(shí)是淺拷貝,指向了同一個(gè)內(nèi)存地址。使用mutableCopy賦值給一個(gè)不可變對(duì)象是深拷貝,重新分配了內(nèi)存空間。
可變字符串
NSMutableString *mtest = [[NSMutableString alloc] initWithString:@"mutableCopy NSSting"];
NSMutableString *mtest4 = [mtest copy]; // 深拷貝
NSMutableString *mtest5 = [mtest mutableCopy]; //深拷貝
打印結(jié)果:
mtest:0x600000445ac0
mtest4:0x600000445c10
mtest5:0x600000445a90
通過copy或mutableCopy的方式賦值給可變對(duì)象,從打印的結(jié)果可以看到它們?nèi)齻€(gè)指向的內(nèi)存地址都是不一樣的,因此都是深拷貝。
集合類對(duì)象的深拷貝與淺拷貝
對(duì)于集合類對(duì)象我們以數(shù)組為例進(jìn)行說明
不可變對(duì)象
NSArray *testArray = @[@"A", @"B", @"C"];
NSArray *testArray1 = [testArray copy]; //淺拷貝
NSArray *testArray2 = [testArray mutableCopy]; //深拷貝
打印結(jié)果:
testArray:0x60400004a4d0
testArray1:0x60400004a4d0
testArray2:0x60400004a770
通過copy賦值testArray1與testArray指向相同的內(nèi)存地址,因此通過copy的方式賦值給不可變對(duì)象是淺拷貝。testArray2是新的內(nèi)存地址,通過mutableCopy的方式賦值給一個(gè)不可變對(duì)象是深拷貝。
可變對(duì)象
NSMutableArray *mTestArray = [[NSMutableArray alloc] init];
NSMutableArray *mTestArray1 = [mTestArray copy]; //深拷貝
NSMutableArray *mTestArray2 = [mTestArray mutableCopy]; //淺拷貝
打印結(jié)果:
testArray:0x60800005ba50
testArray1:0x60c000004910
testArray2:0x60800005bc00
無論是copy還是mutableCopy賦值給一個(gè)可變對(duì)象時(shí)都是深拷貝。
集合對(duì)象的值
打印數(shù)組的第一個(gè)值的內(nèi)存地址
NSLog(@"testArray 1value:%p", [mTestArray objectAtIndex:0]);
NSLog(@"testArray1 1value:%p", [mTestArray1 objectAtIndex:0]);
NSLog(@"testArray2 1value:%p", [mTestArray2 objectAtIndex:0]);
打印結(jié)果:
testArray 1value:0x104b67238
testArray1 1value:0x104b67238
testArray2 1value:0x104b67238
我們看到打印的結(jié)果第一個(gè)值都指向了同一個(gè)內(nèi)存地址,這說明集合對(duì)象的深拷貝只是單層深拷貝,只是給該對(duì)象分配了一個(gè)新的內(nèi)存地址而集合對(duì)象里面的值還都指向原來的內(nèi)存地址。
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);
打印結(jié)果:
test:0x10b07e088
pTest:0x10b07e088
mtest:0x6040002410e0
mpTest:0x604000241770
通過打印結(jié)果我們可以看到不可變對(duì)象是淺拷貝,可變度對(duì)象是深拷貝。其實(shí)看到set方法的實(shí)現(xiàn)原來我們就明白了property里的copy什么時(shí)候是深拷貝,什么時(shí)候是淺拷貝
- (void)setPTest:(NSString *)pTest {
_pTest = [pTest copy];
}