object-c 中的手动内存管理

manual memory-management in object-c

阅读本文时,我对 object-c 中的手动内存管理有疑问 guide

为了让问题更清楚,我把我困惑的代码贴在下面:

// CarStore.m
- (void)setInventory:(NSMutableArray *)newInventory {
    if (_inventory == newInventory) {
        return;
    }
    NSMutableArray *oldValue = _inventory;
    _inventory = [newInventory retain];
    [oldValue release];
}

我认为上面的代码做了重复操作:

// CarStore.m
- (void)setInventory:(NSMutableArray *)newInventory {
    // if we can ensure '_inventory' is different with 'newInventory'
    if (_inventory == newInventory) {
        return;
    }

    // we can release '_inventory' firstly and safely
    [_inventory release];
    _inventory = [newInventory retain];
}

还有

// CarStore.m
- (void)setInventory:(NSMutableArray *)newInventory {
    // if we don't check the equal between '_inventory' and 'newInventory' firstly
    // then we need temp '_inventory', since '_inventory' and 'newInventory' maybe the same object
    NSMutableArray *oldValue = _inventory;
    _inventory = [newInventory retain];
    [oldValue release];
}

不知道自己的想法有没有错误,还请指教

你大部分是正确的,你的两个版本都很常见。

不过,中间代码段存在一个微妙的潜在问题。 newInventory 可能与 _inventory 不同,但释放 _inventory 仍会导致 newInventory 被释放。这是因为如果 newInventory 直接或间接地包含在 _inventory.

中,那么唯一剩下的对 newInventory 的强引用可能是 _inventory 本身。

您还可以使用第三种形式来避免对临时变量的需要:

- (void)setInventory:(NSMutableArray *)newInventory {
    [newInventory retain];
    [_inventory release];
    _inventory = newInventory;
}

最后,即使对于正确的内存管理来说并非绝对必要,您也可能有一些原因希望包括相等性检查。例如,尽管 Apple 努力使 -retain-release 变快,但它们并不是免费的。因此,如果值没有真正发生变化,跳过它们可能仍然会提高效率。

此外,您可能希望在 setter 中进行其他工作,例如将视图标记为需要显示或使相关的缓存值无效。如果值没有真正改变,您可能希望避免这样做。