这些指针的有效性

Validity of these pointers

我目前正在努力提高对指针和 ARC 的掌握。 考虑以下示例

@implementation Foobar

-(NSArray *)methodA {
    return self.someArray;
}

-(NSArray *)methodB {
    return [[NSArray alloc] init];
}

@end
@interface Foo : NSObject
@property(strong) NSArray * myArrayA;
@property(strong) NSArray * myArrayB;
@end

@implementation Foo

-(void)fooMethod {
    //suppose f is an instance of foobar
    self.myArrayA = [f methodA];  //---->statement 1
    self.myArrayB = [f methodB];  //---->statement 2
    //Destructor of f instance is called.
    //Will myArrayA and myArrayB be valid ?
}

@end

现在 fooMethod class foo 有数组的两个强属性 myArrayAmyArrayB 现在 myArrayA 引用了一个强数组来自 class 实例 foobar 的指针,但是 myArrayB 正在引用一个在作用域中创建的强指针。现在假设以某种方式调用了实例 f 的析构函数。当调用该析构函数时,它将清除 SomeArray 的内容,从而使 myArrayA 无效,但是由于其析构函数不知道 MethodB 分配的内存,因此内存仍然存在。我的理解是,如果实例 f 在语句 2 之后被销毁,则 myArrayA 指向的地址将无效,而 myArrayB 指向的地址将有效。如果我的理解正确,请告诉我。

假设ffoobar的一个实例,当你调用[f MethodA](并且方法名应该命名为likeThis)时,它将return self.SomeArray;self.myArrayA 将保存一个指向数组 returned 的强指针,无论 f 的状态如何(是否 dealloced)。

同样地,[f MethodB] returns [[NSArray alloc]init],所以 self.myArrayB 将持有指向您刚刚创建的那个实例的强指针,它将一直持有到您将 self.myArrayB 设置为零。

在Objective-C中,当一个对象不复存在时调用的方法叫做dealloc,我们倾向于简称为dealloc,不要不要称它为 "destructor",尽管 dealloc 非常接近于其他语言的析构函数。

然而,话虽如此,ARC 禁止您直接调用对象上的 dealloc。如果您直接在一个对象上调用 dealloc,如果您使用的是 ARC,您的项目将不会编译。

相反,ARC 写入您的内存管理代码。在某个对象的剩余强引用为零之后的某个时刻(不能保证立即发生),ARC 将释放您的对象。但重要的是,一个对象可以有 任意数量 的强引用。那么,让我们看一下您的具体示例。

在您的示例中,

f 是 class Foobar 的已实例化实例,它具有 属性 someArray。您无法显示 属性 的声明方式,但我们假设它的声明方式与 Foo 中的属性声明方式相同(如 strong)。在任何时候 someArray 属性 变为非零,至少有一个对该数组的强引用。

为了论证,我们假设 f 是对该数组的唯一强引用。这将使数组的引用计数等于一。

现在,在 Foo 中,我们将 myArrayA 设置为 fsomeArray 属性。这个数组现在有两个强引用——引用计数等于二。

同时,FoomyArrayB 被设置为等于新实例化的 NSArray 对象。 f 没有保留对此数组的强引用。一旦 methodB returns,只有 Foo class 的 myArrayB 对数组具有强引用。它的引用计数等于一。

现在,假设我们保留 f(通过任何方式),但我们的 Foo 实例被释放(但是),这两个数组会发生什么?

因为我们的 Foo 实例被释放,它将不再持有对任一数组的强引用。 ARC 会将每个数组的引用计数减一。

FoomyArrayA 的引用计数将从 2 减为 1--f 仍然持有强引用,数组不会被释放。

FoomyArrayB 的引用计数将从 1 减为 0——没有其他对象持有对 myArrayB 的强引用,因此引用计数为零, ARC 将释放此数组。