[转载]深刻理解iOS中的“深拷贝”和“浅拷贝”
- 浅拷贝就是拷贝后,并没有进行真正的复制,而是复制的对象和原对象都指向同一个地址
- 深拷贝是真正的复制了一份,复制的对象指向了新的地址

浅拷贝 < ----- > 深拷贝
通俗理解为:浅拷贝好比你的影子,你死了,影子也没了;深拷贝好比克隆人,你死了,它还在。
深拷贝和浅拷贝的本质是地址是否相同
在开发过程中,大体上会区分为对象和容器两个概念,对象的copy是浅拷贝,mutablecopy是深拷贝。容器包含对象的拷贝,无论是copy,还是mutablecopy都是浅拷贝,要想实现对象的深拷贝,必须自己提供拷贝方法
- 非容器不可变对象:NSString
- 费容器可变对象: NSMutableString
- 容器类不可变对象: NSArray
- 容器类可变对象: NSMutableArray
代码测试
非容器不可变对象
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 : 0x104c4a068, class: __NSCFConstantString
str2_p : 0x104c4a068, class: __NSCFConstantString str3_p : 0x61000006db00, class: __NSCFString
结论:
- 对于非容器不可变对象的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 : 0x618000260140, class: __NSCFString
str2_p : 0x61800004efd0, class: __NSCFString str3_p : 0x6180002602c0, class: __NSCFString
结论:
- 对于非容器可变对象的copy为深拷贝
- mutableCopy为深拷贝
- 并且copy和mutableCopy返回对象都为可变对象
容器不可变对象
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: 0x610000024ac0, class: __NSArrayI
copyArray_p: 0x610000024ac0, class: __NSArrayI mutableCopyArray_p: 0x610000242610, class: __NSArrayM ======原对象===== object_p: 0x61000006f540, class: __NSCFString object_p: 0x10c386080, class: __NSCFConstantString ======copy对象===== object_p: 0x61000006f540, class: __NSCFString object_p: 0x10c386080, class: __NSCFConstantString ======mutableCopy对象===== object_p: 0x61000006f540, class: __NSCFString object_p: 0x10c386080, class: __NSCFConstantString
结论:
从上述输出中可以看出容器类不可变对象mutableCopy确实返回一个新的容器,但容器内的元素仍然是浅拷贝
容器可变对象
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: 0x6100000552d0, class: __NSArrayM
copyArray_p: 0x610000031340, class: __NSArrayI mutableCopyArray_p: 0x610000055000, class: __NSArrayM ======原对象===== object_p: 0x610000267300, class: __NSCFString object_p: 0x107070080, class: __NSCFConstantString ======copy对象===== object_p: 0x610000267300, class: __NSCFString object_p: 0x107070080, class: __NSCFConstantString ======mutableCopy对象===== object_p: 0x610000267300, class: __NSCFString object_p: 0x107070080, class: __NSCFConstantString
结论:
从上述输出中可以看出容器类可变对象mutableCopy和copy都返回一个新的容器,但容器内的元素仍然是浅拷贝
总结:
通过上述代码分析:- copy: 对于可变对象为深拷贝,对于不可变对象为浅拷贝
- mutableCopy:始终是深拷贝
自定义类对象的深浅拷贝
在OC中不是所有的类都支持拷贝,只有遵循<NSCopying>才支持copy,只有遵循<NSMutableCopying>才支持mutableCopy。如果没有遵循,拷贝时会直接Crash。代码示例:#import <Foundation/Foundation.h>
@interface Person : NSObject <NSCopying, NSMutableCopying> @property (nonatomic, copy) NSString *name; @end #import "Person.h" @implementation Person - (id)copyWithZone:(NSZone *)zone { Person *person = [Person allocWithZone:zone]; person.name = self.name; return person; } - (id)mutableCopyWithZone:(NSZone *)zone { Person *person = [Person allocWithZone:zone]; person.name = self.name; return person; } @end
实现容器对象的完全拷贝
NSMutableString *str1 = [NSMutableString stringWithFormat:@"非容器可变对象"];
NSArray *array = [NSArray arrayWithObjects:str1, @"非容器不可变对象", nil]; NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithArray:array copyItems:YES]; NSData *data = [NSKeyedArchiver archivedDataWithRootObject:mutableArray]; NSMutableArray *newMutableArray = [NSKeyedUnarchiver unarchiveObjectWithData:data]; NSLog(@"===原对象==="); NSLog(@"array[0] : %p, array[1] : %p", array[0], array[1]); NSLog(@"===新对象==="); NSLog(@"mutableArray[0] : %p, mutableArray[1] : %p", mutableArray[0], mutableArray[1]); NSLog(@"===完全拷贝对象==="); NSLog(@"newMutableArray[0] : %p, newMutableArray[1] : %p", newMutableArray[0], newMutableArray[1]);
输出:
===原对象===
array[0] : 0x6180000697c0, array[1] : 0x10f40f098 ===新对象=== mutableArray[0] : 0x618000055060, mutableArray[1] : 0x10f40f098 ===完全拷贝对象=== newMutableArray[0] : 0x618000055600, newMutableArray[1] : 0x6180000556f0
如果是自定义类对象 需要遵循<NSCoding>否则在使用NSKeyedArchiver的时候会Crash自定义对象代码如下
#import <Foundation/Foundation.h>
@interface Person : NSObject <NSCoding> @property (nonatomic, copy) NSString *name; @end #import "Person.h" @implementation Person - (instancetype)initWithCoder:(NSCoder *)aDecoder { self.name = [aDecoder decodeObjectForKey:@"name"]; return self; } - (void)encodeWithCoder:(NSCoder *)aCoder { [aCoder encodeObject:self.name forKey:@"name"]; } @end
T
转载于:https://www.cnblogs.com/1-434/p/10496795.html
最后
以上就是大气小兔子最近收集整理的关于iOS面试题整理---iOS中的“深拷贝”和“浅拷贝”的全部内容,更多相关iOS面试题整理---iOS中内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复