美文网首页
Objective-C中的浅拷贝&深拷贝

Objective-C中的浅拷贝&深拷贝

作者: _桃夭大人_ | 来源:发表于2021-01-27 14:34 被阅读0次

    首先介绍一下浅拷贝和深拷贝的概念。

    • 浅拷贝:是指针拷贝,让拷贝前和拷贝后对象的指针指向同一块内存地址。
    • 增加了拷贝前原对象的引用计数
    • 没有新的内存分配
    • 深拷贝:是内存拷贝,让拷贝前和拷贝后对象的指针 指向内容相同的两块内存地址。
    • 不会增加引用计数
    • 产生新的内存分配

    1. 系统类对象的浅拷贝和深拷贝

    下面通过代码 看一下对于可变对象和不可变对象的深拷贝、浅拷贝的区别:

    NSString * myString = @"this is a string";
    NSString * myStringCopy = [myString copy];
    NSMutableString * myStringMutableCopy = [myString mutableCopy];
    NSLog(@"myString的地址 = %p",myString);
    NSLog(@"myStringCopy的地址 = %p",myStringCopy);
    NSLog(@"myStringMutableCopy的地址 = %p",myStringMutableCopy);
            
    NSMutableString * myMutableString = [[NSMutableString alloc]initWithString:@"this is a mutableString"];
    NSString * myMutableStringCopy = [myMutableString copy];
    NSMutableString * myMutableStringMutableCopy = [myMutableString mutableCopy];
    NSLog(@"myMutableString的地址 = %p",myMutableString);
    NSLog(@"myMutableStringCopy的地址 = %p",myMutableStringCopy);
    NSLog(@"myMutableStringMutableCopy的地址 = %p",myMutableStringMutableCopy);
    

    运行上面代码打印如下:

    // 不可变对象拷贝打印
    myString的地址 = 0x1006b21e0
    myStringCopy的地址 = 0x1006b21e0
    myStringMutableCopy的地址 = 0x6000037ba340
    // 可变对象拷贝打印
    myMutableString的地址 = 0x6000037b9ef0
    myMutableStringCopy的地址 = 0x6000037b9fb0
    myMutableStringMutableCopy的地址 = 0x6000037ba370
    

    结论:

    • 对于不可变对象

    copy 是浅拷贝 生成的对象是不可变对象。
    mutableCopy 是深拷贝 生成的对象是可变对象。

    • 对于可变对象

    copy 是深拷贝 生成的对象是不可变对象。
    mutableCopy 是深拷贝 生成的是可变对象。

    2. 自定义类对象的浅拷贝和深拷贝

    在Objective-C语言中 不是所有类都支持拷贝。
    只有遵循<NSCopying>协议才支持copy方法,
    只有遵循<NSMutableCopying>协议才支持mutableCopy方法,否则会造成崩溃。

    这里需要注意父类和子类都实现<NSCopying>协议情况

    // 父类实现copyWithZone方法
    @implementation MyBlockObject
    - (id) copyWithZone:(NSZone *)zone{
    // 这里是重点注意的地方
        MyBlockObject * blk = [[[self class] alloc]init];
        blk.blockObjectStr = self.blockObjectStr;
        return blk;
    }
    @end
    // 子类实现copyWithZone方法
    @implementation MyBlockSubObject
    - (id)copyWithZone:(NSZone *)zone{
        MyBlockSubObject * subObj = [super copyWithZone:zone];
        subObj.mysubString = self.mysubString;
        return subObj;
    }
    @end
    

    3.copy作为属性修饰符

    根据上面1中得出的结论

    copy操作对于不可变对象是浅拷贝,对于可变对象是深拷贝。生成的都是不可变对象。所以copy一般作为不可变类型的属性修饰符。

    @interface ViewController ()
    // 对不可变对象进行copy操作后的目标对象
    @property (nonatomic, copy) NSString * myCopyimmutableStringString;
    // 对可变对象进行copy操作后的目标对象
    @property (nonatomic, copy) NSString * myCopyMutableString;
    
    @end
    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSString * immutableString = @"this is immutableString.";
        self.myCopyimmutableStringString = immutableString;
        NSLog(@"immutableString的地址 = %p    self.myCopyimmutableStringString的地址 = %p",immutableString,self.myCopyimmutableStringString);
    
        NSMutableString * mutableString = [[NSMutableString alloc]initWithString:@"this is mutableString."];
        self.myCopyMutableString = mutableString;
        NSLog(@"mutableString的地址 = %p    self.myCopyMutableString的地址 = %p",mutableString,self.myCopyMutableString);
        [mutableString appendString:@"!!!"];
        NSLog(@"self.myCopyMutableString 的值:%@",self.myCopyMutableString);
    }
    
    @end
    

    打印结果

    immutableString的地址 = 0x10d1ac220 
    self.myCopyimmutableStringString的地址 = 0x10d1ac220
    
    mutableString的地址 = 0x600002839b00   
    self.myCopyMutableString的地址 = 0x6000028399b0
    // 赋值对象发生改变不会影响原对象的值
    self.myCopyMutableString 的值:this is mutableString.
    
    

    结论:

    copy作为属性修饰符在赋值时
    如果赋值对象为不可变对象,那发生的是浅拷贝;
    如果赋值的对象是可变对象,那发生的是深拷贝;
    从而保证了在赋值对象发生改变时,不会影响copy修饰的对象的值。

    这里也证明了 为什么对于不可变类的最好不要使用strong作为修饰符。是因为strong作为属性修饰符,在赋值时是浅拷贝。在赋值对象是可变对象时,赋值对象改变会影响原对象的值。

    相关文章

      网友评论

          本文标题:Objective-C中的浅拷贝&深拷贝

          本文链接:https://www.haomeiwen.com/subject/fgnozktx.html