【问题标题】:Does the assignment operator make a shallow copy of an NSArray?赋值运算符是否制作了 NSArray 的浅表副本?
【发布时间】:2024-01-23 10:09:01
【问题描述】:

假设我有两个数组:

NSArray *A = @[@"Red", @"Blue", @"Yellow"];
NSArray *B = A;

B 在技术上是 A 的浅拷贝吗?如果我对 A 中包含的数据进行更改,B 会看到相同的更改,反之亦然。在查看 Apple 文档中的复制时,没有提到通过“=”运算符进行的简单相等是进行浅复制的有效方法。如果这不构成浅拷贝,那又是什么呢?

【问题讨论】:

    标签: objective-c cocoa cocoa-touch copy nsarray


    【解决方案1】:

    分配(在 Objective-C 中)根本不是副本。也就是说,它不是对象的副本,它只是对象引用的副本。每个对象(引用)都必须声明为指针是有原因的。 (块是一种特殊情况。)

    浅拷贝是通过copy方法完成的,如:NSArray *B = [A copy];

    碰巧你不能修改 NSArrays,但原则也适用于 NSMutableArrays。

    NSMutableArray *a = [@[@"Red", @"Blue", @"Yellow"] mutableCopy];
    NSMutableArray *b = a;
    NSMutableArray *c = [a mutableCopy];
    
    NSLog(@"%@, %@, %@", a[0], b[0], c[0]);  // Prints: Red, Red, Red
    
    b[0] = @"Green";
    
    NSLog(@"%@, %@, %@", a[0], b[0], c[0]);  // Prints: Green, Green, Red
    
    c[0] = @"Purple";
    
    NSLog(@"%@, %@, %@", a[0], b[0], c[0]);  // Prints: Green, Green, Purple
    

    【讨论】:

    • 快速提问,如果赋值是引用的副本,如您所说,那与浅拷贝不一样吗?
    • 第二种情况,a[0]和b[0]都变成@"Green",是不是因为b是a的浅拷贝?您通过使用赋值运算符实现了这一点,这是我混淆浅拷贝与赋值的基础。它们都复制对内存中对象的引用。
    • 数组的浅拷贝复制数组中包含的每个引用(指针)。深拷贝实际上会复制每个对象。想想一个邮政信箱。你给你的朋友一把钥匙,现在他或你可以访问同一个邮政信箱。那是参考副本/作业。相反,如果他有自己的邮政信箱,复印你信箱中的所有信件并将副本放入他的邮箱,那么他制作的副本很浅。
    • 因此,在这种情况下,深层副本将是邮政信箱及其中所有字母的精确副本。很好的例子,很有帮助。
    • 有时您正在复制的对象指向其他对象。如果您制作的副本仅复制指向其他对象的指针,则您制作了浅拷贝。如果您复制所指向的对象,并使您的副本指向那些其他对象的新副本,那么您已经进行了深层复制。深层副本通常必须递归才能完成。
    最近更新 更多