浅拷贝和深拷贝的区别

前言

  • 在iOS中并不是所有对象都支持copy和mutableCopy的.必须要遵守两个协议.只有遵守了这两个协议的类才有权限发送copy和mutableCopy消息,我自己试验了一把,如果我没有遵守协议,copyWithZone以及mutableCopyWithZone是没有提示的,如果我们强制运行这两个方法,程序会直接崩溃.当让如果我们直接调用copy和mutableCopy对象方法,运行也会崩溃,提示我们需要遵守这两个协议

  • 浅拷贝

    • 所谓的浅拷贝就是拷贝指向对象的指针,意思就是说:拷贝出来的目标对象的指针和源对象的指针指向的内存空间是同一块空间.
    • 浅拷贝只是一种简单的拷贝,让几个对象公用一个内存,然而当内存销毁的时候,指向这个内存空间的所有指针需要重新定义,不然会造成野指针错误
  • 深拷贝

    • 所谓的深拷贝指拷贝对象的具体内容,其内容地址是自助分配的,拷贝结束之后,内存中的值是完全相同的,但是内存地址是不一样的,两个对象之间相互不影响,也互不干涉.
  • 我们来总结一下两者之间的原理 : 如果现在有一个A对象,拷贝之后得到一份新的对象A_Copy,如果时浅拷贝,那么A对象和A_Copy对象指向的就是同一个内存的资源,它拷贝的只是一个指针而已,对象的内容并没有拷贝.也就是说对象的资源还是只有一份.如果这个时候我们对A_copy对象进行修改操作,那么A对象的内容同样会被修改.然而如果是深拷贝,拷贝的不仅仅是指针,还有内容,拷贝的对象B_Copy会自助分配内存,两个对象的指针指向的是不同的内存空间,因为A对象和B_Copy对象的内存地址是不一样的,所以,如果我们对B_Copy进行修改操作的话是不会影响到A对象,它们之间是互不干涉的

  • 浅拷贝就想是您和您的影子之间的关系 : 你挂了, 你的影子也跟着挂了

  • 深拷贝就像是您的克隆人, 你挂啦, 可你的克隆人还活着

浅拷贝和深拷贝的应用

  • oc中哪些操作实现浅拷贝:

    • 第一条:retain操作,始终是浅复制。返回对象是否可变与被复制的对象保持一致。

    • 在 iOS 里面, 使用retain 关键字进行引用计数,就是一种更加保险的浅拷贝。他既让几个指针共用同一片内存空间,又可以在release 由于计数的存在,不会轻易的销毁内存,达到更加简单使用的目的。

  • 第二条:copy操作,对于不可变对象是浅复制。引用计数每次加一。始终返回一个不可变对象。

  • oc中哪些操作实现深拷贝:

  • 第一条:copy操作,对于可变对象为深复制,引用计数不改变。

  • 第二条:mutableCopy操作:始终是深复制,引用计数不改变。始终返回一个可变对象。

代码示例

    NSString *text = @"WilliamAlex";

    NSString *text1 = [text copy];
    NSString *text2 = [text mutableCopy];
    NSMutableString *text3 = [text copy];
    NSMutableString *text4 = [text mutableCopy];

    NSLog(@"text=%p,text1=%p",text,text1);
    NSLog(@"text=%p,text1=%p",text,text2);
    NSLog(@"text=%p,text1=%p",text,text3);
    NSLog(@"text=%p,text1=%p",text,text4);

打印结果

浅拷贝和深拷贝[716:38840] text=0x10697f068,text1=0x10697f068
浅拷贝和深拷贝[716:38840] text=0x10697f068,text2=0x7fce33c74be0
浅拷贝和深拷贝[716:38840] text=0x10697f068,text3=0x10697f068
浅拷贝和深拷贝[716:38840] text=0x10697f068,text4=0x7fce33c783d0
  • 注意 :

  • 注意需要遵循<NSCopying, NSMutableCopying>两个协议,否则程序会崩溃

  • 从打印结果中可以看出,text1,text3的地址和text是一样的,text2和text3和text是不一样的.可以得出结论

    • 1, 说明了使用mutableCopy拷贝出了新的对象 :它们的地址不一样,说明了它们生成了新对象
    • 2, 使用了copy,它们的地址是一样的,说明拷贝的只是指针,不会拷贝对象自身.说明它们不会产生新对像.
  • 总结 : 在字符串是直接赋值的时候,判断是否生成新对象是和等号"="右边有直接有关,如果右边是mutableCopy那么就会生成新的对象,如果是copy就不会产生新的对象. 这时候的copy就是浅拷贝,而mutableCopy就是深拷贝

stringWithFormat:方法的字符串

 NSString *text = [NSString stringWithFormat:@"WilliamAlex"];

    NSString *text1 = [text copy];
    NSString *text2 = [text mutableCopy];
    NSMutableString *text3 = [text copy];
    NSMutableString *text4 = [text mutableCopy];

    NSLog(@"text=%p,text1=%p",text,text1);
    NSLog(@"text=%p,text1=%p",text,text2);
    NSLog(@"text=%p,text1=%p",text,text3);
    NSLog(@"text=%p,text1=%p",text,text4);

打印结果

浅拷贝和深拷贝[734:43455] text=0x7fbaca70c890,text1=0x7fbaca70c890
浅拷贝和深拷贝[734:43455] text=0x7fbaca70c890,text1=0x7fbaca70d760
浅拷贝和深拷贝[734:43455] text=0x7fbaca70c890,text1=0x7fbaca70c890
浅拷贝和深拷贝[734:43455] text=0x7fbaca70c890,text1=0x7fbaca70d7a0
  • 结果和直接赋值完全一样

stringWithString:方法的字符串


    NSString *text = [NSMutableString stringWithString:@"WilliamAlex"];

    NSString *text1 = [text copy];
    NSString *text2 = [text mutableCopy];
    NSMutableString *text3 = [text copy];
    NSMutableString *text4 = [text mutableCopy];

    NSLog(@"text=%p,text1=%p",text,text1);
    NSLog(@"text=%p,text1=%p",text,text2);
    NSLog(@"text=%p,text1=%p",text,text3);
    NSLog(@"text=%p,text1=%p",text,text4);

打印结果

浅拷贝和深拷贝[762:45587] text=0x7fbd495aaf20,text1=0x7fbd495aac50
浅拷贝和深拷贝[762:45587] text=0x7fbd495aaf20,text1=0x7fbd495afad0
浅拷贝和深拷贝[762:45587] text=0x7fbd495aaf20,text1=0x7fbd495af810
浅拷贝和深拷贝[762:45587] text=0x7fbd495aaf20,text1=0x7fbd495acdf0

  • 结果全部都不一样

  • 总结 : 根据代码,等号"="右边从创建一直到赋值,它包含了一个NSMutableCopying,所以它会重新生成一个对象,copy是指针拷贝,而mutableCopy是对象拷贝.

你可能感兴趣的:(浅拷贝和深拷贝的区别)