深拷贝和浅拷贝
浅拷贝就是你和张三放一个风筝,
深拷贝就是你买了一个跟张三一模一样的风筝.
浅拷贝: 也叫位拷贝,只对指针的拷贝,拷贝后两个指针指向同一个内存空间.
深拷贝: 也叫值拷贝,对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针.
NSString *srcStr = @"123";
NSMutableString *copyStr = [srcStr mutableCopy];
[copyStr appendString:@"abc"];
NSLog(@"srcStr=%p:%@, copyStr=%p:%@", srcStr,srcStr, copyStr,copyStr);
浅拷贝会出现什么问题?
- 浅拷贝只拷贝了指针,使得两个指针指向同一个地址,对象释放时,会造成同一份资源析构2次,造成程序崩溃.也就会引起常见的僵尸对象(zombie).
- 浅拷贝指针指向同一块内存,任何一方的变动都会影响到另一方.
深拷贝会出现什么问题?
深拷贝都是在堆内存中申请新的空间来存储数据,可以避免指针悬挂.
- 都使用深拷贝会造成资源浪费.
- 深拷贝只能拷贝一层,
要想拷贝第二层,必须是第二层的对象也实现NSCopy协议.
NSArray *array = @[@"1",@"2",@"3"];
NSMutableArray *mutableArray = [array mutableCopy];
[mutableArray addObject:@"4"];
NSLog(@"array地址:%p,array=%@\nmutableArray地址:%p,mutableArray=%@",array,array,mutableArray,mutableArray);
NSCopying和NSMutableCopying
自定义类想要支持 copy
和 mutableCopy
方法就需要实现 NSCopying
和 NSMutableCopying
协议。
@interface People : NSObject <NSCopying,NSMutableCopying>
@property (nonatomic,copy) NSString *name;
@end
@implementation People
- (id)init
{
self = [super init];
if (self) {
self.name = @"";
}
return self;
}
// copyWithZone: 方法相当于创建一个新对象,并将当前对象的值复制到新创建的对象中。设置时应直接访问成员变量而不是属性。
- (id)copyWithZone:(nullable NSZone *)zone
{
// 直接从 NSObject 继承的类应该使用此方法
// 父类已经实现此方法的应该调用 [super copyWithZone:zone]
People *p = [[self class] allocWithZone:zone];
p.name = [_name copyWithZone:zone];
return p;
}
- (id)mutableCopyWithZone:(nullable NSZone *)zone
{
People *p = [[self class] allocWithZone:zone];
p.name = [_name mutableCopyWithZone:zone];
return p;
}
@end
People *p1 = [[People alloc] init];
p1.name = @"1";
People *p2 = [People new];
p2.name = @"2";
People *p3 = [People new];
p3.name = @"3";
NSArray *array = @[p1,p2,p3];
NSMutableArray *mutableArray = [array mutableCopy];
People *pe3 = mutableArray[2];
pe3.name = @"pe3";
People *pe4 = [People new];
pe4.name = @"3";
[mutableArray addObject:pe4];
//copy和mutableCopy的区别
People *pe33 = [pe3 copy];
People *pe333 = [pe3 mutableCopy];
pe333.name = @"pe333";
NSLog(@"array地址:%p,array=%@\nmutableArray地址:%p,mutableArray=%@",array,array,mutableArray,mutableArray);
log日志:
array地址:0x6000000509b0,array=(
"<People: 0x60000000f670>",
"<People: 0x60000000f680>",
"<People: 0x60000000f690>"
)
mutableArray地址:0x6000000509e0,mutableArray=(
"<People: 0x60000000f670>",
"<People: 0x60000000f680>",
"<People: 0x60000000f690>",
"<People: 0x60000000f0f0>"
)
在对array
进行mutableCopy
后,数组地址发生了改变,但是数组内people对象的地址并未发生改变.