【问题标题】:How does ARC work in the following code snippet in ios?ARC 在 ios 的以下代码片段中如何工作?
【发布时间】:2019-05-12 13:57:46
【问题描述】:

假设我有一个返回对象指针的方法

-(MyObj *) returnMyObj {
   MyObj *obj = [MyObj alloc] init];
   return obj;
}

如果我调用这个函数而不像这样分配指针

场景 1

[self returnMyObj];

如果我调用这个函数并赋值给这样的指针

场景 2

MyObj* obj = [self returnMyObj];

编译器可以在场景 1 中的 returnMyObj 方法调用结束时释放对象,但在场景 2 中不能这样做。ARC 如何决定是否需要将创建的对象保留在两种情况下方法调用是否结束?

【问题讨论】:

    标签: objective-c automatic-ref-counting


    【解决方案1】:

    如果后面的块中没有引用obj,优化器可能会在语句末尾完全释放场景2中的对象。

    关键是优化器可以看到指针何时被引用,并可能在最后一次引用完成后立即释放它。 obj 没有精确的生命周期语义,因此它只会延长对象的生命周期,直到最后一次引用 obj,而不是当 obj 超出范围时。

    在场景1中,引用没有分配给任何变量,所以它显然没有以后的引用,并且可能立即释放。也就是说,它可能不会立即释放该对象,因为returnMyObj 不会将所有权转移给调用者(由于其名称)。因此,在自动释放池耗尽之前,该对象可能不会真正被释放。

    【讨论】:

    【解决方案2】:

    以下是文档中的 ARC article 所说的:

    为确保实例在仍然需要时不会消失,ARC 会跟踪当前引用每个类实例的属性、常量和变量的数量。只要至少一个对该实例的活动引用仍然存在,ARC 就不会释放该实例。

    为了实现这一点,每当您将类实例分配给属性、常量或变量时,该属性、常量或变量都会对该实例进行强引用。该引用被称为“强”引用,因为它牢牢控制该实例,并且只要该强引用仍然存在,就不允许释放它。

    ARC 通过计算对对象的强引用来决定哪些对象将保留在内存中,哪些对象将被释放。

    在您的第二种情况下,您正在创建对 MyObj 实例的强引用,并且 ARC 在对象正在使用时不会释放它。在这种情况下,它将在使用该对象的方法完成时被释放。

    【讨论】:

    • 我会在此处删除短语“将保留计数增加 1”。对于像这样的自动变量,它通常永远不会这样做(保留计数是在运行时维护的内部细节)。但它确实创建了一个编译器和优化器在编译时跟踪的“参考”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-16
    • 2015-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多