美文网首页
iOS 你不一定了解的深浅拷贝

iOS 你不一定了解的深浅拷贝

作者: Ching_Han | 来源:发表于2017-08-15 18:17 被阅读199次

一、深浅拷贝

1、 什么是深拷贝?

深拷贝是对内容的拷贝,复制内容,同时有新的指针指向该内存区域;

2、什么是浅拷贝?

浅拷贝只做指针复制,两个指针指向同一处内存空间;

3、对于拷贝,详细来说有四方面内容:

1、不可变对象的拷贝操作:immutableObjc -> copy
2、不可变对象的可变拷贝操作:immutableObjc -> mutableCopy
3、可变对象的拷贝操作:mutableObjc -> copy
4、可变对象的可变拷贝操作:mutableObjc -> mutableCopy

二、非集合对象的深浅拷贝(NSString、NSNumber...)

1、不可变对象的 copy 和 mutableCopy

NSString *string = @"string";
NSString *copyString = [string copy]; // 没有产生新对象
NSMutableString *mutCopyString = [string mutableCopy]; // 产生新对象
    
NSLog(@"\n string = %p\n copyString = %p\n mutCopyString = %p", string, copyString, mutCopyString);

打印结果:

不可变对象的 copy 和 mutablecopy

结论:对不可变对象 copy 是浅拷贝,mutablecopy 是深拷贝;

2、可变对象的 copy 和 mutableCopy

NSMutableString *string = [NSMutableString stringWithString:@"mutString"];

NSString *copyString = [string copy]; // 产生新对象
NSMutableString *mutCopyString = [string mutableCopy];  // 产生新对象

NSLog(@"\n string = %p\n copyString = %p\n mutCopyString = %p", string, copyString, mutCopyString);

打印结果:

可变对象的 copy 和 mutablecopy

结论:对可变对象 copy 和 mutablecopy 都是深拷贝;

3、非集合对象的深浅拷贝:

  • immutableObjc -> copy 浅拷贝
  • immutableObjc -> mutableCopy 深拷贝
  • mutableObjc -> copy 深拷贝
  • mutableObjc -> mutableCopy 深拷贝

三、集合对象的深浅拷贝(NSArray、NSSet、NSDictionary)

1、集合的浅复制 (shallow copy)

集合的浅复制有非常多种方法。当你进行浅复制时,会向原始的集合发送retain消息,引用计数加1,同时指针被拷贝到新的集合。
现在让我们看一些浅复制的例子:

NSArray *shallowCopyArray = [someArray copyWithZone:nil];
NSSet *shallowCopySet = [NSSet mutableCopyWithZone:nil];
NSDictionary *shallowCopyDict = [[NSDictionary alloc] initWithDictionary:someDictionary copyItems:NO];
2、集合的深复制 (deep copy)

方式一:用 initWithArray:copyItems: 将第二个参数设置为YES

NSDictionary *shallowCopyDict = [[NSDictionary alloc] initWithDictionary:someDictionary copyItems:YES];

如果使用这种方法深复制,集合里的每个对象都会收到 copyWithZone: 消息。如果集合里的对象遵循 NSCopying 协议,那么对象就会被深复制到新的集合。如果对象没有遵循 NSCopying 协议,而尝试用这种方法进行深复制,会在运行时出错。copyWithZone: 这种拷贝方式只能够提供一层内存拷贝(one-level-deep copy),而非真正的深复制。

方式二:将集合进行归档(archive),然后解档(unarchive)

NSArray *trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:oldArray]];
3、集合的单层深复制 (one-level-deep copy)

什么是单层深复制呢?如果在多层数组中,对第一层进行内容拷贝,其它层进行指针拷贝,这种情况,即为单层深复制。苹果的官方文档
苹果认为这种复制不是真正的深复制,而是将其称为单层深复制(one-level-deep copy)。因此,有人对浅复制、单层深复制、深复制做了概念区分。

  • 浅复制(shallow copy):在浅复制操作时,对于被复制对象的每一层都是指针复制。
  • 单层深复制(one-level-deep copy):在深复制操作时,对于被复制对象,至少有一层是深复制。
  • 完全复制(real-deep copy):在完全复制操作时,对于被复制对象的每一层都是对象复制。

1、不可变对象的 copy 和 mutableCopy

 NSArray *array = @[@[@"a", @"b"], @[@"c", @"d"]];
 NSArray *copyArray = [array copy];
 NSMutableArray *mutCopyArray = [array mutableCopy];

 NSLog(@"\narray - %p\ncopy - %p\nmutCopy - %p", array, copyArray, mutCopyArray);

打印结果:

集合 immutable 对象的拷贝

结论:

  • 查看内容,可以看到 copyArray 和 array 的地址是一样的,而 mutCopyArray 和 array 的地址是不同的。说明 copy 操作进行了指针拷贝,mutableCopy 进行了内容拷贝。
  • 需要强调的是:此处的内容拷贝,仅仅是拷贝 array 这个对象,array 集合内部的元素仍然是指针拷贝。这和上面的非集合 immutable 对象的拷贝还是挺相似的,

2、可变对象的 copy 和 mutableCopy

NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"], @"b", @"c", nil];
NSArray *copyArray = [array copy];
NSMutableArray *mutCopyArray = [array mutableCopy];
    
NSLog(@"\narray - %p\ncopy - %p\nmutCopy - %p", array, copyArray, mutCopyArray);

查看结果:

集合 mutable 对象的拷贝

结论:

  • 根据打印结果可以看到 copyArray、mutCopyArray 和array 的内存地址都不一样,说明 copyArray、 mutCopyArray 都对 array 进行了内容拷贝。
  • 在集合类对象中,对 immutable 对象进行 copy,是指针复制,mutableCopy 是内容复制;对 mutable 对象进行 copy 和 mutableCopy 都是内容复制。但是:集合对象的内容复制仅限于对象本身,对象元素仍然是指针复制。
4、集合对象的深浅拷贝
  • [immutableObject copy] // 浅复制
  • [immutableObject mutableCopy] //单层深复制
  • [mutableObject copy] //单层深复制
  • [mutableObject mutableCopy] //单层深复制

四、自定义对象

需要遵守<NSCopying>协议,并实现协议方法

CHIPerson *person = [[CHIPerson alloc] init];
CHIPerson *copyPerson = [person copy];
    
NSLog(@"\n person = %p\n copyPerson = %p\n", person, copyPerson);
- (id)copyWithZone:(NSZone *)zone
{
    CHIPerson *person = [[self class] allocWithZone:zone];
    return person;
}

打印结果:

自定义对象的拷贝操作

结论:自定义对象的拷贝操作是深拷贝

本文参考链接:

集合深浅拷贝以及经常遇到的坑
iOS 集合的深复制与浅复制

相关文章

  • iOS 深浅拷贝

    iOS深浅拷贝

  • iOS 你不一定了解的深浅拷贝

    一、深浅拷贝 1、 什么是深拷贝? 深拷贝是对内容的拷贝,复制内容,同时有新的指针指向该内存区域; 2、什么是浅拷...

  • Copy基础理解(一)

    关于oc深浅拷贝问题可能做过ios开发的都有了解到,尤其是面试特别喜欢问深浅拷贝的问题.但大多有点误区,即便是有几...

  • iOS深浅拷贝

    授权转载,作者:西木柚子 OC对象的三种拷贝方式 OC的对象拷贝有如下三种方式,很多时候我们把深复制和完全复制混为...

  • iOS深浅拷贝

    简述深浅拷贝 我们实例化的对象存储在堆区,而指向对象的指针一般存储在栈区。我们需要知道这个前提。  实际上拷贝分为...

  • iOS深浅拷贝

    浅拷贝:复制一个指针,仍然指向已经存在的内存深拷贝:复制一个指针,并新申请一个内存 关于拷贝的引用计数:浅拷贝:a...

  • iOS 深浅拷贝

    一、引言 我们都知道,iOS中的对象,遵守NSCopying 协议的类可以发送copy消息,遵守NSMutable...

  • iOS 深浅拷贝

    http://www.cocoachina.com/cms/wap.php?action=article&id=2...

  • iOS深浅拷贝

    (本文根据CocoaChina上的一篇帖子整理,后期附上链接)最开始,我们需要清楚一些关于内存分配方式的基础知识。...

  • iOS深浅拷贝

    引言 在对于自定义的对象支持copy功能,也就是我们要给自定义的对象发送copy message,那我们就要手动实...

网友评论

      本文标题:iOS 你不一定了解的深浅拷贝

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