【OC】深浅拷贝

深浅拷贝的基本定义

在这里插入图片描述

浅拷贝:指创建一个新对象,但新对象仍然引用原对象的内部数据。这种拷贝方式对于性能和内存管理很有优势,但需要注意一些潜在的风险。
深拷贝:指创建一个新对象,并将原对象的所有属性和子对象都复制到新对象中,形成一个完全独立的拷贝。
下面借助之前看到的两张图片来帮助理解
深拷贝
在这里插入图片描述
浅拷贝
在这里插入图片描述

对于非集合元素的深浅拷贝

NSString:

        NSString* a = @"hello";
        NSString* b = [a copy];
        NSString* c = [a mutableCopy];
        NSMutableString* d = [a copy];
        NSMutableString* e = [a mutableCopy];
        NSLog(@"%p", a);
        NSLog(@"%p", b);
        NSLog(@"%p", c);
        NSLog(@"%p", d);
        NSLog(@"%p", e);

运行结果
在这里插入图片描述
NSMutableString

        NSMutableString* a = [NSMutableString stringWithFormat:@"hello,world"];
        NSString* b = [a copy];
        NSString* c = [a mutableCopy];
        NSMutableString* d = [a copy];
        NSMutableString* e = [a mutableCopy];
        NSLog(@"%p", a);
        NSLog(@"%p", b);
        NSLog(@"%p", c);
        NSLog(@"%p", d);
        NSLog(@"%p", e);

运行结果
在这里插入图片描述
结论
由上面两个测试结果可以看出,对于NSString对象来说,当进行不可变复制(copy)时,进行浅拷贝,仅复制了指针地址;进行可变复制(MutableCopy)时,进行深拷贝,既复制了指针也复制了所指内容。对于NSMutableString对象来说,无论进行哪种复制,为了保证复制对象可以进行改变,都进行了深拷贝。

对于集合元素的深浅拷贝

NSArray:

        NSArray* arr = [NSArray arrayWithObjects:@"a",@"b",@"c",@"d", nil];
        NSArray* arrcopy = [arr copy];
        NSMutableArray* arrmucopy = [arr mutableCopy];
        NSLog(@"%p", arr);
        NSLog(@"%p", arrcopy);
        NSLog(@"%p", arrmucopy);
        NSLog(@"%p", arr[0]);
        NSLog(@"%p", arrcopy[0]);
        NSLog(@"%p", arrmucopy[0]);

运行结果
在这里插入图片描述
arrcopy进行浅拷贝,被复制的对象和复制对象都不可以改变,仅复制了指针。
arrmucopy进行深拷贝,故而复制指针和所指内容
集合内的元素均进行浅拷贝,故而地址相同。
NSMutableArray

        NSMutableArray* arr = [NSMutableArray arrayWithObjects:@"a",@"b",@"c",@"d", nil];
        NSMutableArray* arrcopy = [arr copy];
        NSMutableArray* arrmucopy = [arr mutableCopy];
        NSLog(@"%p", arr);
        NSLog(@"%p", arrcopy);
        NSLog(@"%p", arrmucopy);
        NSLog(@"%p", arr[0]);
        NSLog(@"%p", arrcopy[0]);
        NSLog(@"%p", arrmucopy[0]);

运行结果
在这里插入图片描述
对可变数组进行复制,均进行深拷贝,既复制指针也复制所指的内容。
集合内的元素均进行浅拷贝,故而打印的地址相同。

注意:为什么集合内元素均为浅拷贝?(这里借助chat进行讲解,如果不对后期再回来改正)。
在这里插入图片描述

容器类元素的完全深拷贝

在进行完全深拷贝时,被复制对象的每一层都是对象复制。
copyItems
copyItems: 方法是 NSArray 和 NSMutableArray 的一个方法,用于创建一个新的数组,并对数组中的元素进行拷贝。该方法会遍历原始数组的每个元素,并对每个元素执行 copy 操作,然后将拷贝后的元素添加到新的数组中。
接口部分

@interface Person : NSObject <NSMutableCopying, NSCopying>
@property (nonatomic, strong) NSMutableString* name;
@end

实现部分

@implementation Person
-(id) copyWithZone:(NSZone *)zone
{
    Person* star = [[[self class]allocWithZone:zone]init];
    star.name = [self.name mutableCopy];
    return star;
}

-(id) mutableCopyWithZone:(NSZone *)zone
{
    Person* star = [[[self class]allocWithZone:zone]init];
    star.name = [self.name mutableCopy];
    return star;
}
@end

测试程序

NSArray*  arr1= [[NSArray alloc]initWithObjects:a, nil];
        NSArray*  arr2 = [[NSArray alloc]initWithArray:arr1 copyItems:YES];
        Person* p1 = [arr1 objectAtIndex:0];
        Person* p2 = [arr2 objectAtIndex:0];
        NSLog(@"%p %p", arr1, arr2);
        NSLog(@"%p %p", p1, p2);
        NSLog(@"%p %@", p1.name, p1.name);
        NSLog(@"%p %@", p2.name, p2.name);

运行结果
在这里插入图片描述
由运行结果可以看出,使用copyItems不仅对数组进行拷贝,同时对数组内的元素也进行深拷贝。

递归重写copyWithZone方法

@implementation Person
-(id) copyWithZone:(NSZone *)zone
{
    Person* star = [[[self class]allocWithZone:zone]init];
    star.name = [self.name mutableCopy];
    return star;
}

-(id) mutableCopyWithZone:(NSZone *)zone
{
    Person* star = [[[self class]allocWithZone:zone]init];
    star.name = [self.name mutableCopy];
    return star;
}
@end

        Person* a = [[Person alloc] init];
        a.name = [NSMutableString stringWithFormat:@"张三"];
        Person* b = [a copy];
        Person* c = [a mutableCopy];
        NSLog(@"%p", a);
        NSLog(@"%p", b);
        NSLog(@"%p", c);
        NSLog(@"%p %p %p", a.name, b.name, c.name);

运行结果
在这里插入图片描述

由运行结果可以看出,这样就实现了完全拷贝。

  • 15
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值