iOS 深拷贝 浅拷贝 完全拷贝
一:概念
浅拷贝:指针拷贝,不会创建一个新的对象。浅拷贝简单点说就是对内存地址的复制,让目标对象指针和源对象指针指向同一片内存空间
深拷贝: 内容拷贝,会创建一个新的对象。深拷贝就是拷贝地址中的内容,让目标对象产生新的内存区域,且将源内存区域中的内容复制到目标内存区域中
深拷贝和浅拷贝的本质是内存地址是否相同
单层深拷贝:基于容器对象,其第一层子元素是深拷贝。一般copyItems在子元素都是可变对象时,会达到这种效果。
完全拷贝:基于容器对象,其所有元素都是深拷贝的情况下,叫做完全拷贝。
非容器不可变对象 copy 与mutableCopy的区别
NSString *str1 = @"非容器不可变对象";
NSString *str2 = [str1 copy];
NSString *str3 = [str1 mutableCopy];
NSLog(@"str1_p : %p, class: %@", str1, [str1 class]);
NSLog(@"str2_p : %p, class: %@", str2, [str2 class]);
NSLog(@"str3_p : %p, class: %@", str3, [str3 class]);
控制台输出
str1_p : 0x108274020, class: __NSCFConstantString
str2_p : 0x108274020, class: __NSCFConstantString
str3_p : 0x600000a79680, class: __NSCFString
结论:
1.对于非容器不可变对象的copy为浅拷贝,mutableCopy为深拷贝
2.浅拷贝获得的对象地址和原对象地址一致, 返回的对象为不可变对象
3.深拷贝返回新的内存地址,返回对象为可变对象
非容器可变对象 copy 与mutableCopy的区别
NSMutableString *str1 = [NSMutableString stringWithFormat:@"非容器可变对象"];
NSMutableString *str2 = [str1 copy];
NSMutableString *str3 = [str1 mutableCopy];
NSLog(@"str1_p : %p, class: %@", str1, [str1 class]);
NSLog(@"str2_p : %p, class: %@", str2, [str2 class]);
NSLog(@"str3_p : %p, class: %@", str3, [str3 class]);
控制台输出
str1_p : 0x6000020a30c0, class: __NSCFString
str2_p : 0x6000020a2ee0, class: __NSCFString
str3_p : 0x6000020a3000, class: __NSCFString
结论:
1.对于非容器可变对象的copy为深拷贝
2.mutableCopy为深拷贝
3.并且copy和mutableCopy返回对象都为可变对象
可变容器对象
NSMutableString *str1 = [NSMutableString stringWithFormat:@"非容器可变对象"];
NSString *str2 = @"非容器不可变对象";
NSMutableArray *array = [NSMutableArray arrayWithObjects:str1, str2, nil];
NSMutableArray *copyArray = [array copy];
NSMutableArray *mutableCopyArray = [array mutableCopy];
NSMutableArray *copyItemsArray = [[NSMutableArray alloc]initWithArray:array copyItems:YES];
NSArray *copyItemsArray1 = [[NSArray alloc]initWithArray:array copyItems:YES];
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(@"copyItemsArray: %p, class: %@", copyItemsArray, [copyItemsArray class]);
NSLog(@"copyItemsArray1: %p, class: %@", copyItemsArray1, [copyItemsArray1 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]);
NSLog(@"======copyItems对象=====");
NSLog(@"object_p: %p, class: %@", copyItemsArray[0], [copyItemsArray[0] class]);
NSLog(@"object_p: %p, class: %@", copyItemsArray[1], [copyItemsArray[1] class]);
NSLog(@"======copyItems1对象=====");
NSLog(@"object_p: %p, class: %@", copyItemsArray1[0], [copyItemsArray1[0] class]);
NSLog(@"object_p: %p, class: %@", copyItemsArray1[1], [copyItemsArray1[1] class]);
控制台输出
array_p: 0x6000025ab210, class: __NSArrayM
copyArray_p: 0x600002bac060, class: __NSArrayI
mutableCopyArray_p: 0x6000025abcc0, class: __NSArrayM
copyItemsArray: 0x6000025abde0, class: __NSArrayM
======原对象=====
object_p: 0x6000025ab840, class: __NSCFString
object_p: 0x10da1e040, class: __NSCFConstantString
======copy对象=====
object_p: 0x6000025ab840, class: __NSCFString
object_p: 0x10da1e040, class: __NSCFConstantString
======mutableCopy对象=====
object_p: 0x6000025ab840, class: __NSCFString
object_p: 0x10da1e040, class: __NSCFConstantString
======copyItems对象=====
object_p: 0x6000025abe70, class: __NSCFString
object_p: 0x10da1e040, class: __NSCFConstantString
======copyItems1对象=====
object_p: 0x6000003e1590, class: __NSCFString
object_p: 0x1095fc040, class: __NSCFConstantString
结论:
1.对可变容器来说 copy和mutableCopy,copyItems都是深拷贝,
2.copy出来的是不可变容器。mutableCopy出来的是可变容器
3.子元素来说mutableCopy,copy都是浅拷贝,copyItems相当于对每个子元素执行copy,非容器可变对象(str1)copy是深拷贝,非容器不可变对象(str2)copy是浅拷贝
不可变容器
NSMutableString *str1 = [NSMutableString stringWithFormat:@"非容器可变对象"];
NSString *str2 = @"非容器不可变对象";
NSArray *array = [NSArray arrayWithObjects:str1, str2, nil];
NSMutableArray *copyArray = [array copy];
NSArray *mutableCopyArray = [array mutableCopy];
NSMutableArray *copyItemsMutableArray = [[NSMutableArray alloc]initWithArray:array copyItems:YES];
NSArray *copyItemsArray = [[NSArray alloc]initWithArray:array copyItems:YES];
NSArray *archiverArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array]];
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(@"copyItemsMutableArray: %p, class: %@", copyItemsMutableArray, [copyItemsMutableArray class]);
NSLog(@"copyItemsArray: %p, class: %@", copyItemsArray, [copyItemsArray class]);
NSLog(@"archiverArray: %p, class: %@", archiverArray, [archiverArray 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]);
NSLog(@"======copyItemsMutableArray对象=====");
NSLog(@"object_p: %p, class: %@", copyItemsMutableArray[0], [copyItemsMutableArray[0] class]);
NSLog(@"object_p: %p, class: %@", copyItemsMutableArray[1], [copyItemsMutableArray[1] class]);
NSLog(@"======copyItemsArray对象=====");
NSLog(@"object_p: %p, class: %@", copyItemsArray[0], [copyItemsArray[0] class]);
NSLog(@"object_p: %p, class: %@", copyItemsArray[1], [copyItemsArray[1] class]);
NSLog(@"======archiverArray对象=====");
NSLog(@"object_p: %p, class: %@", archiverArray[0], [archiverArray[0] class]);
NSLog(@"object_p: %p, class: %@", copyItemsArray[1], [archiverArray[1] class]);
控制台输出
array_p: 0x6000028933a0, class: __NSArrayI
copyArray_p: 0x6000028933a0, class: __NSArrayI
mutableCopyArray_p: 0x6000026cccc0, class: __NSArrayM
copyItemsMutableArray: 0x6000026ccf60, class: __NSArrayM
copyItemsArray: 0x6000028933e0, class: __NSArrayI
======原对象=====
object_p: 0x6000026cd080, class: __NSCFString
object_p: 0x10878e040, class: __NSCFConstantString
======copy对象=====
object_p: 0x6000026cd080, class: __NSCFString
object_p: 0x10878e040, class: __NSCFConstantString
======mutableCopy对象=====
object_p: 0x6000026cd080, class: __NSCFString
object_p: 0x10878e040, class: __NSCFConstantString
======copyItemsMutableArray对象=====
object_p: 0x6000026ccc00, class: __NSCFString
object_p: 0x10878e040, class: __NSCFConstantString
======copyItemsArray对象=====
object_p: 0x6000026ccea0, class: __NSCFString
object_p: 0x10878e040, class: __NSCFConstantString
======archiverArray对象=====
object_p: 0x600000a79c50, class: __NSCFString
object_p: 0x600000a79530, class: __NSCFString
结论:
1.不可变容器copy是浅拷贝 mutableCopy是深拷贝 copyItems是深拷贝
2.其余与可变容器完全一样
总结:
当数据结构较为复杂时,如容器里还有容器,若想达到完全拷贝,只有归档解档能实现,copyItems最多只能做到单层深拷贝。