【问题标题】:what is the difference between retain and assign [duplicate]保留和分配有什么区别[重复]
【发布时间】:2016-12-21 15:30:14
【问题描述】:

我搜索了很多链接并阅读了很多文章,但我找不到 retainassign 的确切区别..

我正在尝试以下方法:

NSMutableArray *arr1 = [[NSMutableArray alloc] initWithObjects:@"1",@"2",@"3", nil];
NSMutableArray *arr2=[arr1 retain];
NSMutableArray *arr3 = arr1; //Assign

[arr1 addObject:@"66"];

NSLog(@"Array one   : %@",arr1);
NSLog(@"Array two   : %@",arr2);
NSLog(@"Array three : %@",arr3);

输出:

Array one   : (
    1,
    2,
    3,
    66 
)  

Array two   : (
        1,
        2,
        3,
        66
)  

Array three : (
        1,
        2,
        3,
        66 
)

上面的例子给了我同样的输出。

考虑到上面的例子,我如何定义assignretain之间的区别?

如果上面的例子是错误的,请给出更好的例子。

【问题讨论】:

  • 不应再使用保留。使用 ARC,但要回答您的问题(并假设您没有使用 ARC),如果您这样做 [arr2 release],请查看 arr3 会发生什么

标签: ios objective-c memory-management automatic-ref-counting reference-counting


【解决方案1】:

您正在查看指向同一个对象的三个不同变量,因此当然当您显示输出时,每次都会看到同一个对象。

retainassign 是内存限定符的类型,但不影响底层对象是什么。具体来说,它们只影响底层对象的retainCount

让我们看看你的三行代码:

NSMutableArray *arr1 = [[NSMutableArray alloc] initWithObjects:@"1",@"2",@"3", nil];

这会创建一个保留计数为 +1 的对象。

NSMutableArray *arr2 = [arr1 retain];

这会将该对象的保留计数增加到 +2,并且您还有另一个变量指向同一对象。

NSMutableArray *arr3 = arr1; //Assign

这不会进一步增加保留计数,您现在有第三个变量指向同一个对象。


“引用计数”内存管理的基本游戏是确保:

  • 正在使用的对象具有正的保留计数(因此在您仍在使用它时它不会被释放)...未能正确执行此操作可能会导致对象被过早释放,可能给你留下悬而未决的参考;和

  • 您不再使用的对象将其retainCount 减为零,因此当自动释放池耗尽时,该对象将被释放...未能在正确的位置递减计数器可能导致对象泄露。

您可以想象,这会导致一个相当脆弱的过程,我们必须确保在正确的位置使用retainreleaseautorelease 增加和减少保留计数。 Xcode 的“静态分析器”(Xcode 的“产品”菜单上的“分析器”选项或按 shift+command+B)做得很好查看我们的代码并确定我们是否正确地完成了这项工作。如果你正在编写手动引用计数代码,这个工具是必不可少的。

但是,“automatic reference counting”的美妙之处在于,我们将这个递增和递减对象retainCount 值的愚蠢世界抛在了身后。我们转移到一个可以专注于“object graph”的世界,我们在代码中的某些位置需要什么样的引用,编译器会为我们处理 retainCount 的递增和递减。

【讨论】:

    【解决方案2】:

    assignretain 是 Objective-C 中与内存管理相关的两种策略。

    请看: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html

    无论如何,对一个对象调用 retain 并不会改变它的值,所以你会得到相同的输出是正常的。

    retain / release 在 iOS 早期在 Objective-C 中引入并普及,当时苹果出于性能考虑禁止在 iOS 开发中使用垃圾收集器。由于缺少垃圾收集器,开发人员不得不在不再需要对象销毁时手动处理它们。因此,这是一个相当大的挑战,retain / release 当时是帮助开发人员更好地处理此问题的一种方式。

    从 iOS 5 开始,Apple 引入了 ARC(自动引用计数),它必须用于任何新的开发,尤其是在您不熟悉内存管理的情况下。 ARC 允许开发人员停止使用保留/释放来管理对象生命周期,因为在编译过程中添加了内存管理代码(即[object retain][object release])。 开发人员在声明属性时只需要关心内存管理:

    @property(assign) int value;
    @property(strong) id object;
    @property (weak) id object;
    

    在这种情况下strong和retain是相似的,可以互换。强和弱只是新词,让初学者更容易理解幕后发生的事情。 另外 assign 是假定默认值,然后就没有必要了。

    标记为强的属性将在 setObject 期间收到保留调用:标记为弱的属性不会。由于retain 只针对对象(在Heap 中实例化),基本C 类型属性(bool、int、float、struct...)由于它们在Stack 中实例化,因此应标记为assign。

    如果你在一段代码中看到了retain,那只是这个类没有使用ARC,它只是内存管理代码。

    【讨论】:

      【解决方案3】:

      所有 3 个引用都指向同一个实例。

      NSMutableArray *arr2=[arr1 retain]; .
      增加引用计数并返回指向同一实例的指针(即self)。

      NSMutableArray *arr3 = arr1;
      直接分配 arr1 引用,而不通过任何方法调用传递它。

      唯一的区别是您在一种情况下增加了引用计数,而在另一种情况下却没有。
      分配参考的机制是相同的。引用是直接的 (arr3 = arr1) 还是间接的,通过在 arr1 上调用返回对自身的引用的方法,都没有关系。

      【讨论】:

        猜你喜欢
        • 2011-05-04
        • 2011-01-24
        • 2020-08-12
        • 2012-09-24
        • 1970-01-01
        • 2017-02-17
        • 2011-09-27
        • 2013-04-22
        • 2012-03-29
        相关资源
        最近更新 更多