Objective c 指定初始值设定项,是否保留参数?

Objective c 指定初始值设定项,是否保留参数?,objective-c,memory-management,Objective C,Memory Management,我有以下指定的初始值设定项: -(id) initWithName:(NSString*)name; -(id) init { return [self initWithName:@"foo"]; } -(id) init { return [self initWithName:[NSString new]]; } 和以下默认初始值设定项: -(id) initWithName:(NSString*)name; -(id) init { return [self initWithName

我有以下指定的初始值设定项:

-(id) initWithName:(NSString*)name;
-(id) init { return [self initWithName:@"foo"]; }
-(id) init { return [self initWithName:[NSString new]]; }
和以下默认初始值设定项:

-(id) initWithName:(NSString*)name;
-(id) init { return [self initWithName:@"foo"]; }
-(id) init { return [self initWithName:[NSString new]]; }
指定的初始值设定项接收的对象是什么?释放的还是自动释放的

给定以下初始值设定项:

-(id) initWithName:(NSString*)name;
-(id) init { return [self initWithName:@"foo"]; }
-(id) init { return [self initWithName:[NSString new]]; }
我将收到一个重定时对象。默认的初始值设定项永远不会有机会释放它,所以我不应该保留它?。
现在想象一下,这将是一个不提供方便的初始值设定项(如-myClassWithParam:)的类,而不是NSString。我是否需要提供一个方便的初始值设定项来启用就地构造?

您应该始终向初始值设定者发送一个自动释放的对象(或在之后释放它)——内存管理规则在此实例中不会更改

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

-(id) init {return [self initWithName:[[NSString new] autorelease]]]}
这将修复内存泄漏,并且仍然允许就地构建

但是,在传递初始值设定项时,您不需要额外的retain—您使用
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会被调用两次),但更安全。

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

NSString文本的内存管理是一种特殊情况,因为这些对象从不释放,只需忽略
retain
release
autorelease


您的第三个示例有一个漏洞,因为name参数string对象从未被释放。

[[NSString new]autorelease]
是一种模糊的方式,表示
[NSString string]
或只是
@“
我不太喜欢您对初始值设定项所做的操作。参数计数最少的init方法应该使用一个或多个参数调用init方法,在这里,您为额外的参数传递一个默认变量(可能是nil)。我会在你使用的练习中迷失方向,但这可能只是一个风格问题。Cocoa的方法是使用我前面描述的机制。你可以在我的下载类中看到一个典型的例子:(第61-119行)@Nikolai关于保留self,我回答了问题的一部分,他问指定的初始化器是否应该保留init返回的对象。我也知道[NSString]和@“”,但我试图避免使用字符串文字和方便的方法,因为这正是OP所困惑的。也许我应该使用另一个类。@iKenndac据我所知,Johannes从来没有说过要保留待初始化对象,而是只保留字符串参数。更一般地说,任何方法都不应该关心它接收的对象的所有权。一个方法应该依赖的唯一一件事(除非它声称拥有所有权)是一个参数将在该方法的有效期内继续存在。感谢这一澄清,我自己也想到了这一点,但希望有一些其他的输入。你可以猜到,我对obj-c还很陌生