object-c 中的手动内存管理

Posted

技术标签:

【中文标题】object-c 中的手动内存管理【英文标题】:manual memory-management in object-c 【发布时间】:2015-04-07 07:46:04 【问题描述】:

当我阅读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];

我不确定我的想法是否有一些错误,所以请帮帮我。

【问题讨论】:

【参考方案1】:

您基本上是正确的,并且您的任何一个版本都很常见。

不过,中间的 sn-p 存在一个微妙的潜在问题。 newInventory 可能与 _inventory 不同,但释放 _inventory 仍将导致 newInventory 被释放。这是因为如果newInventory 直接或间接包含在_inventory 中,那么对newInventory 的唯一剩余强引用可能是_inventory 本身。

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

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

最后,您可能希望包含相等性检查,即使这对于正确的内存管理并不是绝对必要的。例如,尽管 Apple 努力使 -retain-release 快速,但它们并不是免费的。因此,如果值没有真正改变,跳过它们可能仍然是一种效率改进。

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

【讨论】:

以上是关于object-c 中的手动内存管理的主要内容,如果未能解决你的问题,请参考以下文章

iphone(object-c) 内存管理 有效的内存管理 后半部分

object-c的内存管理机制

读书笔记iOS-属性中的内存管理参数

VBA中的StringFromIID - 避免手动管理内存的好方法是啥?

内存管理

iOS面试题之内存管理