【问题标题】:Deep Copy and Shallow Copy深拷贝和浅拷贝
【发布时间】:2012-04-12 08:34:17
【问题描述】:

我已经从帖子What is the difference between a deep copy and a shallow copy? 中阅读了关于深拷贝和浅拷贝之间区别的答案。现在我有点怀疑,当我们通过

制作浅拷贝时
 newArray = [NSmutableArray arrayWithArray:oldArray];

新数组将指向 oldArray。 (如图)。现在当我从 newArray 中删除对象时会发生什么?如图所示,它也应该从 oldArray 中删除相同的元素!!!好像

newArray = oldArray 是浅拷贝,newArray = [NSmutableArray arrayWithArray:oldArray]; 是深拷贝。对吗?

【问题讨论】:

标签: iphone nsarray


【解决方案1】:

newArary = oldArray 根本不是副本。你最终会得到两个指向完全相同的内存位置的指针。

newArray = [NSMutableArray arrayWithArray:oldArray]; 是浅拷贝。您最终会得到两个不同的数组,因此如果您要从一个数组中删除或添加项目,它不会影响另一个数组。但是,两个数组中的 items 是相同的。如果oldArray 的第一个元素是NSMutableDictionary 并且您为其添加了一个键,那么您也会在newArray 的第一个元素上看到这种变化(因为这两个对象是相同的)。

要进行深拷贝,您必须创建一个新数组,新数组的每个元素都是旧数组对应元素的深拷贝。 (是的,该定义是递归的)。

【讨论】:

  • 根据 Apple (developer.apple.com/library/ios/documentation/General/…),因此如果对象 A 浅复制到对象 B,则对象 B 引用对象 A 引用的相同实例变量(或属性)。因此 newArray = [NSMutableArray arrayWithArray:oldArray];是深拷贝不是浅拷贝。如果我错了,请纠正我。
【解决方案2】:

首先,NSArray 没有深拷贝功能。但是,您可以通过执行以下操作来制作深拷贝功能:

@interface NSArray(deepCopy)

-(NSArray *) deepCopy;

@end

@implementation

-(NSArray *) deepCopy
{
    NSMutableArray *ret = [NSMutableArray array];

    for (id val in self)
    {
        if ([val conformsToProtocol:@protocol(NSCopying)])
        { 
            [ret addObject:[val copy]];
        }
        else
        {
           [ret addObject:val];
        }
    }

    return ret;
}

@end 

其次,newArray = oldArray 不复制数组。它只是让newArray 指向oldArray 指向的数组。

第三,+arrayWithArray: 对数组进行浅拷贝,这意味着不会复制单个对象。

【讨论】:

  • 我想你忘了 [ret addObject:val]; 周围的 else
  • 我认为[ret addObject:[val copy]] 是内存泄漏假设NSCopying 根据Apple 的文档被采用(copyWithZone: 返回一个由发送者隐式保留的对象)。
  • 假设在这种情况下使用了 ARC(自动引用计数)。
  • [ret addObject:[val copy]];将复制原始数组浅层中的每个元素。那么如果我有一个数组数组使用你的方法(深拷贝),我最终会得到一个内部数组浅拷贝的新数组。这是错误的,不是吗。
  • @عليامين 不,这不是“错误”,而是边缘情况。如果自定义对象的复制实现不进行深度复制(就像它应该做的那样,除了序列化和反序列化之外,我能做的很少。
【解决方案3】:

您也可以拨打[[NSArray alloc] initWithArray:arraytoBeCopied copyItems:YES];

【讨论】:

    【解决方案4】:

    在 Objective-C 中的“复制”关键字只是增加对象的“保留计数”。所以只使用“复制”不会执行复制。

    但是当我们对对象进行更改时,Objective-C 会在那时创建原始对象的副本。

    如果我错了,请纠正我。

    谢谢

    【讨论】:

    • 我认为您的答案不正确。事实上,我有理由确定它不是。
    • 您可以在苹果文档中找到它。谢谢。
    • 真的吗?因为当我查看文档时,我发现 NSObject 说 copy 是 copyWithZone: 的快捷方式,它必须由希望根据 NSCopying 协议启用该功能的子类实现。它指定 CopyWithZone 创建一个具有相同属性的新对象——而不是增加保留计数。此外,自添加 ARC 以来,Apple 已明确禁用所有保留计数的使用。所以说“复制”只是增加一个对象的保留计数是完全错误的,无论你如何切割它。
    • 很抱歉没有更清楚地说明我的立场:我不是在争论你的第二段。据我所知,这是正确的(尽管您链接到的文档指出,它不会产生“真正的”深层副本,因为它只会深入一个级别——IMO,一个缺陷)。我正在与您的第一段特别争论非常。实际上,“复制”确实返回了该类的一个新实例。只是该类的内容是对旧对象的引用,而不是副本。
    猜你喜欢
    • 2015-01-13
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 1970-01-01
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多