在setter中释放副本的位置?

时间:2009-09-30 19:34:50

标签: objective-c cocoa

在我的setter中,我有一个我要复制的传入字符串,以避免在修改原始文件时出现任何问题。

- (void)setName:(NSString *)newName{
    if(name != newName) {
        [name release];
        name = [newName copy];
    }
}

我的问题是:因为我正在复制我应该在哪里发布它,还是我只是自动释放?即。

- (void)setName:(NSString *)newName{
    if(name != newName) {
        [name release];
        name = [[newName copy] autorelease];
    }
}

加里

4 个答案:

答案 0 :(得分:6)

执行copy时,将保留该对象。 这就是你想要的。如果你自动发布它,它最终会被解除分配。所以你的第一个例子是正确的。第二个会崩溃你的应用程序。

如果您担心在取消分配对象时会发生什么,请记住您应release dealloc方法中的任何引用。

答案 1 :(得分:4)

  

在我的setter中,我有一个我要复制的传入字符串,以避免在修改原始文件时出现任何问题。

- (void)setName:(NSString *)newName{
  if(name != newName) {
      [name release];
      name = [newName copy];
  }
}
     

我的问题是:因为我正在复制我应该在哪里发布它,还是我只是自动释放?即。

- (void)setName:(NSString *)newName{
  if(name != newName) {
      [name release];
      name = [[newName copy] autorelease];
  }
}

正如我在your other question上所说,autorelease转换为“稍后发送给自己release”。这意味着它算作一个版本。

所以,你的第二个例子释放旧值name(好),然后复制新的(好),然后将新的一行放到行中(坏),然后放这个现在注定的对象进入了实例变量(非常糟糕)。

第一个示例是正确的,因为在将对象放入实例变量后仍然保留对象。

正如我在你的另一个问题上所说,我认为你应该检讨the memory-management rules

答案 2 :(得分:1)

您的第一个样本是正确的:

- (void)setName:(NSString *)newName{
    if(name != newName) {
        [name release];
        name = [newName copy];
    }
}

但是您怀疑,copy必须与release平衡。假设name具有通常的语义(即,您希望它保持不变,直到包含类的实例被释放),平衡release应该在dealloc中(假设您不是使用垃圾收集):

- (void)dealloc {
    [name release];
    //release other instance variables of type id

    [super dealloc];
}

如果您仍然感到困惑,请重读内存Management Programming Guide for Cocoa

答案 3 :(得分:1)

你的第一个例子是正确的。 Peter Hosey也是如此 - 您应该更好地熟悉内存管理规则。

如果它有帮助,我的首选方法看起来更清洁:

- (void)setName:(NSString *)name
{
  name = [name copy];
  [_name release];
  _name = name;
}