指定的初始化程序,保留参数?

时间:2009-10-15 12:06:19

标签: objective-c memory-management

我有以下指定的初始化程序:

-(id) initWithName:(NSString*)name;

以及以下默认初始值设定项:

-(id) init { return [self initWithName:@"foo"]; }

指定的初始化程序接收的对象是什么?已发布或已自动发布?

给出以下初始化程序:

-(id) init { return [self initWithName:[NSString new]]; }

我会收到一个视网膜对象。默认的初始化程序永远不会有机会释放它,所以我不应该保留它? 现在想象一下,这将是一个不提供便利初始化器(如-myClassWithParam :)的类,而不是NSString。我是否需要提供便利的初始化程序来实现构建?

2 个答案:

答案 0 :(得分:3)

初始值设定项(指定与否)不应该关心它作为参数接收的对象的所有权。如果它想要保留对象,则无论参数来自何处,它都必须复制或保留它。您指定的初始化程序initWithName应在其实现中复制name参数。

NSString文字的内存管理是一种特殊情况,因为这些对象永远不会被释放,只是忽略retainreleaseautorelease

您的第三个示例有泄漏,因为名称参数字符串对象永远不会被释放。

答案 1 :(得分:0)

您应始终将自动释放的对象(或之后将其发布)发送给初始化者 - 在此实例中,内存管理规则不会更改。

在你的例子中,我会这样做:

-(id) init {return [self initWithName:[[NSString new] autorelease]]]}

这将修复您的内存泄漏并仍然允许构建。

但是,在通过初始化程序时,您不需要额外的保留 - 您使用self做的事情很好。通常,+alloc会保留对象一次,-init方法不会进一步保留。当-init调用上升到类树时,[super init]将被调用很多次,但是当对象最终返回给调用者时,该对象应该只被保留一次 - +alloc已经为此做了你。

但是,包含单词init,copy或new的便利方法应返回自动释放的对象。举个例子:

+(MyObject *)objectWithName:(NSString *)aName {
    return [[[MyObject alloc] initWithName:aName] autorelease];
}

FWIW,我通常有-init作为我的指定初始化程序,所以如果我忘记并发送-init到一个对象(或其他人做同样的事情),你就不会得到一个垃圾对象。例如:

-(id)init {
    if (self = [super init]) {
        [self setName:[[NSString new] autorelease]];

        myReallyImportantiVar = [[NSArray alloc] init];
        // etc;
    }
    return self;
}


-(id)initWithName:(NSString  *)aName {
    if (self = [self init]) {
        [self setName:aName];
    }
    return self;
}

这可能效率稍低(当你使用-initWithName:时,setName被调用两次),但它更安全。