在getter方法中保留和自动释放

时间:2011-02-12 23:47:46

标签: objective-c release autorelease getter

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

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

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

2 个答案:

答案 0 :(得分:10)

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

技术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.
}

技术2的性能明显优于技术1,在这种情况下,调用getter的频率远远高于setter。

技术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是一个释放的对象,因此log语句会导致崩溃。

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

答案 1 :(得分:2)

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

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

相关问题