iOS中的浅拷贝和深拷贝

66 阅读3分钟

浅拷贝和深拷贝

浅拷贝

浅拷贝就是对内存地址的复制,让目标对象指针和原对象指针指向同一片内存空间,当内存销毁的时候,指向这片内存的几个指针需要重新定义,否则会变成野指针。
浅拷贝拷贝了原来对象的指针,使原对象的引用计数+1,并没有创建新的对象。

深拷贝

深拷贝就是拷贝对象的具体内容,并开辟新的内存地址,新对象与原对象值相同,但是内存地址不一样,两个对象并没有关联。
深拷贝拷贝了原对象的值,但是开辟了新的内存地址,创建后的新对象和原对象没有任何关系。

区别

深拷贝(内容拷贝)和浅拷贝(指针拷贝)的本质区别在于是否开辟了新的内存地址,是否影响了内存地址的引用计数。

copy 和 mutableCopy(以数组为例子)

- (void)testArrayCopy {
    NSArray *originArray = [[NSArray alloc] initWithObjects:@"张三", @"李四", nil];
    NSArray *copyArray = [originArray copy];
    NSArray *mutableCopyArray = [originArray mutableCopy];

    NSLog(@"originArray: %p --- %@ --- %@", originArray, originArray.class, originArray);
    NSLog(@"copyArray: %p --- %@ --- %@", copyArray, copyArray.class, copyArray);
    NSLog(@"mutableCopyArray: %p --- %@ --- %@", mutableCopyArray, mutableCopyArray.class, mutableCopyArray);

    NSMutableArray *originalMutableArray = [[NSMutableArray alloc] initWithObjects:@"张三", @"李四", nil];
    NSMutableArray *copyMutableArray = [originalMutableArray copy];
    NSMutableArray *mutableCopyMutableArray = [originalMutableArray mutableCopy];

    NSLog(@"originArray: %p --- %@ --- %@", originalMutableArray, originalMutableArray.class, originalMutableArray);
    NSLog(@"copyArray: %p --- %@ --- %@", copyMutableArray, copyMutableArray.class, copyMutableArray);
    NSLog(@"mutableCopyArray: %p --- %@ --- %@", mutableCopyMutableArray, mutableCopyMutableArray.class, mutableCopyMutableArray);
}

打印结果:

originArray: 0x60000026a1e0 --- __NSArrayI --- (
"\U5f20\U4e09",
"\U674e\U56db"
)

copyArray: 0x60000026a1e0 --- __NSArrayI --- (
"\U5f20\U4e09",
"\U674e\U56db"
)

mutableCopyArray: 0x600000c6be70 --- __NSArrayM --- (
"\U5f20\U4e09",
"\U674e\U56db"
)

originArray: 0x600000c61d40 --- __NSArrayM --- (
"\U5f20\U4e09",
"\U674e\U56db"
)

copyArray: 0x60000026a480 --- __NSArrayI --- (
"\U5f20\U4e09",
"\U674e\U56db"
)

mutableCopyArray: 0x600000c625b0 --- __NSArrayM --- (
"\U5f20\U4e09",
"\U674e\U56db"
)

由打印结果可知:

1、对不可变集合对象的 copy 为浅拷贝,拷贝的指针指向原有对象的地址 0x60000026a1e0 2、对不可变集合对象的 mutableCopy 为深拷贝,复制的对象为可变对象__NSArrayM,返回一个新的集合对象 3、对可变集合对象的 copy 为深拷贝,复制对象为不可变对象 __NSArrayI,返回一个新的集合对象 4、对可变集合对象的 mutableCopy 为深拷贝,复制对象为可变对象__NSArrayM,返回一个新的集合对象
即:

对象类型方法拷贝后对象类型拷贝类型是否返回新对象
NSArraycopyNSArray浅拷贝
NSArraymutableCopyNSMutableArray深拷贝
NSMutableArraycopyNSArray浅拷贝
NSMutableArraymutableCopyNSMutableArray浅拷贝

NSCopying 协议

OC 中不是所有的类都支持拷贝,只有遵循了 NSCopying 协议的类才支持 copy,遵循了 NSMutableCopying 协议的类才支持 mutableCopy

@interface YZCopyPropertyModel : NSObject<NSCopying>

@property (nonatomic, copy) NSString *modelID;

@property (nonatomic, copy) NSString *modelMsg;

@end

@implementation YZCopyPropertyModel
- (nonnull id)copyWithZone:(nullable NSZone *)zone {
    YZCopyPropertyModel *model = [[YZCopyPropertyModel allocWithZone:zone] init];
    model.modelID = self.modelID;
    model.modelMsg = self.modelMsg;
    return model;
}

@end

- (void)testCustomCopyClass {

    YZCopyPropertyModel *model = [[YZCopyPropertyModel alloc] init];

    model.modelID = @"1";

    model.modelMsg = @"message";

    YZCopyPropertyModel *model2 = [model copy];

    NSLog(@"model: %p", model);

    NSLog(@"model2: %p", model2);

}

结果:

model: 0x60000021a240
model2: 0x600000219cc0

由打印结果可知自定义类通过重写 copyWithZone 方法实现了深拷贝