美文网首页
copy和mutableCopy

copy和mutableCopy

作者: 雷霸龙 | 来源:发表于2021-04-12 16:02 被阅读0次

    copy和mutableCopy的概念

    copy浅拷贝,不拷贝对象本身,仅仅是拷贝指向对象的指针。

    NSString *str1 = @"str1";
    NSString *str2 = [str1 copy];
    NSLog(@"\nstr1 = %@ str1P = %p \n str2 = %@ str2P = %p", str1, str1, str2, str2);
    
    /*输出结果,可以得出下图结论
      str1 = str1 str1P = 0x104d75180
      str2 = str1 str2P = 0x104d75180 
    */
    
    image.png

    mutableCopy深拷贝,是直接拷贝整个对象内存到另一块内存中。

    NSMutableString *mStr1 = [@"123" mutableCopy];
    NSMutableString *mStr2 = [mStr1 mutableCopy];
    NSLog(@"\n mStr1 = %@ mStr1P = %p \n mStr2 = %@ mStr2P = %p", mStr1, mStr1, mStr2, mStr2);
    /*输出结果,可以得出下图结论
       mStr1 = 123 mStr1P = 0x6000004460c0
       mStr2 = 123 mStr2P = 0x600000446420
    */
    
    image.png
    问题1:上面浅拷贝的情况下,改变str1的值,str2的值会变化吗?
    copy的特点:
    • 修改源对象的属性和行为,不会影响副本对象
    • 修改副本对象的属性和行为,不会影响源对象
    NSString *str1 = @"str1";
    NSString *str2 = [str1 copy];
    
    str1 = @"asdf";
    
    NSLog(@"\nstr1 = %@ str1P = %p \n str2 = %@ str2P = %p", str1, str1, str2, str2);
    
    /*输出结果,修改str2 同理
       str1 = asdf str1P = 0x10776b1a0
       str2 = str1 str2P = 0x10776b180
    */
    

    那为什么NSString *str2 = [str1 copy];是不同的指针指向同一块内存空间,str1重新赋值后两个内存空间就不一样了呢?

    因为str2 = str1的时候,两个字符串都是不可变的,指向的同一块内存空间中的@"str1",是不可能变成@"abcd"的。所以这个时候,为了优化性能,系统没必要另外提供内存,只生成另外一个指针,指向同一块内存空间就行。

    但是当你重新给str1或者str2赋值的时候,因为之前的内容不可变,还有互不影响的原则下,这个时候,系统会重新开辟一块内存空间。

    问题2:copy一个可变的数组,会出现什么结果?
    NSMutableArray *mArr1 = [@[@"123", @"456", @"asd"] mutableCopy];
    NSMutableArray *mArr2 = [mArr1 copy];
    
    NSLog(@"\n mArr1 = %@ mArr1P = %p mArr1 class = %@ \n\n mArr2 = %@ mArr2P = %p mArr2 class = %@", mArr1, mArr1, [mArr1 class], mArr2, mArr2, [mArr2 class]);
    
    /*输出结果
    mArr1 = (
                123,
                456,
                asd
                )
    mArr1P = 0x60400025db20
    mArr1 class = __NSArrayM
    
    mArr2 = (
                123,
                456,
                asd
                )
    mArr2P = 0x60400025dd30
    mArr2 class = __NSArrayI
    */
    

    从结果看出,内存地址不一样,而且mArr2是不可变的。copy为什么不是指针指向了?

    首先,mArr2是通过copy得来的,关键点在于copy,和mArr1无关,所以他是不可变的。

    另外,mArr1指向的内存空间是可变的,如果对mArr1进行修改,同一内存空间的内容就会变化。遵循相会不影响的原则,加上mArr2是不可变的,mArr1的内存空间已经不合适,所以此时的copy重新开辟内存空间。

    问题3:用copy修饰NSMutableArray@property (nonatomic, copy) NSMutableArray *mArr;,对mArr赋值会有什么结果?
    NSArray *arr = @[@"123", @"456", @"asd"];
    self.mArr = [arr mutableCopy];
    NSLog(@"\n arrP = %p \n self.mArrP = %p, self.mArr class = %@", arr, self.mArr, [self.mArr class]);
    
    /*输出结果
     arrP = 0x60000044d1a0
     self.mArrP = 0x60000044d1a0, self.mArr class = __NSArrayI
    */
    

    可以看出内存地址不一样,但是_mArr是不可变的数组。

    因为_mArr声明的时候是用copy修饰,那么就限制了他为不可变的数组。赋值的时候是用mutableCopy,可变数组的复制方法,所以会重新分配内存。

    NSArray *arr = @[@"123", @"456", @"asd"];
    self.mArr = arr;
    NSLog(@"\n arrP = %p \n self.mArrP = %p, self.mArr class = %@", arr, self.mArr, [self.mArr class]);
    
    /*输出结果
     arrP = 0x60400044ecd0
     self.mArrP = 0x60400044ecd0, self.mArr class = __NSArrayI
    */
    

    直接赋值,内存地址没变。

    问题4:浅拷贝,不拷贝对象本身,仅仅是拷贝指向对象的指针。深拷贝,是直接拷贝整个对象内存到另一块内存中。有什么看法?

    浅拷贝,不拷贝对象本身,仅仅是拷贝指向对象的指针。不够严谨,在一些特殊请款下,还是会拷贝整个对象内存到另一块内存中。

    总结:

    • 用copy修饰的或者赋值的变量肯定是不可变的。
    • 用copy赋值,要看源对象是否是可变的,来决定只拷贝指针,还是也拷贝对象到另一块内存空间
    • 对象之间mutableCopy赋值,肯定会拷贝整个对象内存到另一块内存中
    • 对象之间赋值之后,再改变,遵循互不影响的原则

    相关文章

      网友评论

          本文标题:copy和mutableCopy

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