【问题标题】:retain and autorelease in a getter method在 getter 方法中保留和自动释放
【发布时间】:2011-06-26 06:27:20
【问题描述】:

我正在学习内存管理,但我真的不明白为什么我应该像这样实现我的属性 getter:

-(Weapon*)myWeapon
{
    [myWeapon retain];
    [myWeapon autorelease];
    return myWeapon;
}

我理解我写的内容,但我无法想象它为什么重要?你能解释一下我为什么要这样做吗?

【问题讨论】:

    标签: objective-c release autorelease getter


    【解决方案1】:

    这是来自内存管理编程指南:

    技术 1 在技​​术 1 中,getter 返回的值在调用范围内自动释放:

    - (NSString*) title {
        return [[title retain] autorelease];
    }
    
    - (void) setTitle: (NSString*) newTitle {
        if (title != newTitle) {
            [title release];
            title = [newTitle retain]; // Or copy, depending on your needs.
        }
    }
    

    因为从 get 访问器返回的对象是在当前范围内自动释放的,所以如果属性值发生更改,它仍然有效。这使得访问器更加健壮,但代价是额外的开销。如果您希望您的 getter 方法被频繁调用,那么保留和自动释放对象的额外成本可能不值得性能成本。

    技巧 2 与技术 1 一样,技术 2 也使用自动释放技术,但这次在 setter 方法中使用:

    - (NSString*) title {
        return title;
    }
    
    - (void) setTitle: (NSString*) newTitle {
        [title autorelease];
        title = [newTitle retain]; // Or copy, depending on your needs.
    }
    

    在 getter 比 setter 更频繁地调用的情况下,技术 2 的性能明显优于技术 1。

    技术 3 技术 3 完全避免使用自动释放:

    - (NSString*) title {
        return title;
    }
    
    - (void) setTitle: (NSString*) newTitle {
        if (newTitle != title) {
            [title release];
            title = [newTitle retain]; // Or copy, depending on your needs.
        }
    }
    

    技术 3 使用的方法适用于经常调用的 getter 和 setter 方法。它也适用于不想延长其值的生命周期的对象,例如集合类。它的缺点是旧值可能会立即被释放(如果没有其他所有者),如果另一个对象维护对它的非拥有引用,这将导致问题。例如:

    NSString *oldTitle = [anObject title];
    [anObject setTitle:@"New Title"];
    NSLog(@"Old title was: %@", oldTitle);
    

    如果 anObject 是唯一拥有原始标题字符串的对象,则在设置新标题后,该字符串将被释放。日志语句将导致崩溃,因为 oldTitle 是一个已释放的对象。

    编辑:基本上保留然后自动释放的目的是确保如果在调用范围有机会保留它之前更改了属性值,则该对象不会被释放。除非您有异步代码,否则这通常不是问题。在大多数情况下,- (Weapon *)myWeapon { return myWeapon; } 很好(而且速度更快)。

    【讨论】:

    • 百万 THX Rich,最后一个问题:这种技术只推荐在 getter 和/或 setter 中使用???
    • 只有 getter 和 setter 是什么意思,你还想在哪里使用它们?如果你问是否可以这样做而不是使用 getter 和 setter,答案是否定的。除非变量是只读的,否则始终使用 getter 和 setter,在这种情况下,您应该使用技术 3(或者如果它不是对象,即 C 数据类型,则只分配它)来设置初始化程序中的变量(只读变量永远不会改变,所以你不需要自动释放)。
    【解决方案2】:

    正如 ACBurk 所说,但这里有一个很好的描述:

    http://vgable.com/blog/2009/03/31/how-to-write-cocoa-object-getters/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-17
      • 2011-01-24
      • 2012-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多