关于copy和mutableCopy的内容多了一些,所以分开两部分写了,上一篇写到的是非容器类的copy和mutableCopy,这篇主要看容器类的copy和mutableCopy。
二、容器类的浅拷贝和深拷贝
容器类主要是指NSArray和NSMutableArray,NSDictionary和NSMutableDictionary等,这部分的拷贝其实和非容器类的有些相似,不同的地方在于容器内对象的拷贝。
2.1 不可变对象的浅拷贝和深拷贝
NSArray *array = [NSArray arrayWithObjects:@"a", @"b", @"c", @"d", nil]; NSArray *arrayCopy = [array copy]; NSArray *arrayMCopy = [array mutableCopy]; NSMutableArray *marryCopy = [array copy]; NSMutableArray *marrayMCopy = [array mutableCopy]; NSLog(@"array--------%p",array); NSLog(@"arrayCopy----%p",arrayCopy); NSLog(@"arrayMCopy---%p",arrayMCopy); NSLog(@"marryCopy----%p",marryCopy); NSLog(@"marrayMCopy--%p",marrayMCopy); 2015-09-21 10:34:05.725 CopyAndMutableCopyTest[643:34782] array--------0x1002069c0 2015-09-21 10:34:05.726 CopyAndMutableCopyTest[643:34782] arrayCopy----0x1002069c0 2015-09-21 10:34:05.726 CopyAndMutableCopyTest[643:34782] arrayMCopy---0x100207e80 2015-09-21 10:34:05.726 CopyAndMutableCopyTest[643:34782] marryCopy----0x1002069c0 2015-09-21 10:34:05.727 CopyAndMutableCopyTest[643:34782] marrayMCopy--0x100207ed0
array、arrayCopy和arrayMCopy的内存地址是一样的,说明了[array copy]对array进行了一次浅拷贝,即指针复制,然后赋值给arrayCopy 和arrayMCopy,这两个指针指向的地址是同一个对象。
而marrayCopy和marrayMCopy的地址则和array的地址不同,说明他们是不同的对象,[array mutableCopy]对array进行了一次深拷贝,在内存中开辟一块存储区域用于存放新的对象。
但是要注意,不管对array进行的是copy还是mutableCopy,容器类对象array中的对象都只进行指针复制(浅拷贝)。这里如果不懂,看下面的例子就可以明白了。
2.2 可变对象的浅拷贝和深拷贝
NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"], @"b", @"c", @"d", nil]; NSArray *arrayCopy = [array copy]; NSArray *arrayMCopy = [array mutableCopy]; NSMutableArray *marrayCopy = [array copy]; NSMutableArray *marrayMCopy = [array mutableCopy]; //打印所有测试对象 NSLog(@"array--%@", array); NSLog(@"arrayCopy--%@", arrayCopy); NSLog(@"arrayMCopy--%@", arrayMCopy); NSLog(@"marrayCopy--%@", marrayCopy); NSLog(@"marrayMCopy--%@", marrayMCopy); 2015-09-21 10:50:01.954 CopyAndMutableCopyTest[667:40305] array--(a,b,c,d) 2015-09-21 10:50:01.955 CopyAndMutableCopyTest[667:40305] arrayCopy--(a,b,c,d) 2015-09-21 10:50:01.955 CopyAndMutableCopyTest[667:40305] arrayMCopy--(a,b,c,d) 2015-09-21 10:50:01.955 CopyAndMutableCopyTest[667:40305] marrayCopy--(a,b,c,d) 2015-09-21 10:50:01.955 CopyAndMutableCopyTest[667:40305] marrayMCopy--(a,b,c,d) //追加array中的第一个可变对象NSMutableString NSMutableString *testString = [array objectAtIndex:0]; [testString appendString:@"tail"]; //打印所有测试对象 NSLog(@"array--%@", array); NSLog(@"arrayCopy--%@", arrayCopy); NSLog(@"arrayMCopy--%@", arrayMCopy); NSLog(@"marrayCopy--%@", marrayCopy); NSLog(@"marrayMCopy--%@", marrayMCopy); 2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] array--(atail,b,c,d) 2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] arrayCopy--(atail,b,c,d) 2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] arrayMCopy--(atail,b,c,d) 2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] marrayCopy--(atail,b,c,d) 2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] marrayMCopy--(atail,b,c,d) //打印所有测试对象的地址 NSLog(@"array--------%p",array); NSLog(@"arrayCopy----%p",arrayCopy); NSLog(@"arrayMCopy---%p",arrayMCopy); NSLog(@"marryCopy----%p",marrayCopy); NSLog(@"marrayMCopy--%p",marrayMCopy); 2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] array--------0x100206da0 2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] arrayCopy----0x100206fa0 2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] arrayMCopy---0x100207a30 2015-09-21 10:50:01.974 CopyAndMutableCopyTest[667:40305] marryCopy----0x100207a80 2015-09-21 10:50:01.974 CopyAndMutableCopyTest[667:40305] marrayMCopy--0x100207ab0
可以看到每个对象的地址都不一样
2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] array--------0x100206da0
2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] arrayCopy----0x100206fa0
2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] arrayMCopy---0x100207a30
2015-09-21 10:50:01.974 CopyAndMutableCopyTest[667:40305] marryCopy----0x100207a80
2015-09-21 10:50:01.974 CopyAndMutableCopyTest[667:40305] marrayMCopy--0x100207ab0
所以如果是对可变对象array进行的拷贝,则不论是对array进行了mutableCopy还是copy,都会产生新的内存地址,所以这时的拷贝都是深拷贝。
但是!这时候数组包含的对象只进行了指针复制。看代码中的例子,如果我讲array中的第一个可变对象[NSMutableString stringWithString:@"a"]
取出放到testString中来,并追加一个tail
//追加array中的第一个可变对象NSMutableString NSMutableString *testString = [array objectAtIndex:0]; [testString appendString:@"tail"];那么array中的第一个可变对象的内容就会变成atail。
而根据指针复制的特点(如果还不清楚的请看第一篇),因为arrayCopy、arrayMCopy、marryCopy、marrayMCopy里面的第一个对象都指向同一个地址,所以其内容也会跟着改变,这些arrayCopy、arrayMCopy、marryCopy、marrayMCopy数组的第一个对象都会变成atail。
这就是数组包含的对象是指针复制的解释。