【问题标题】:Who should be responsible for the release the setter's parameter?谁应该负责释放setter的参数?
【发布时间】:2013-03-06 06:54:30
【问题描述】:

代码如下:

- (void) setSomeThing:(NSString *) someThingNew
{
     if(someThing!=someThingNew)
     {
         [someThingNew retain];
         [someThing release];
         someThing = someThingNew;
     }
 }

 ... ...
 - (void) dealloc
 {
     [someThing release];
     [super dealloc];
 }
@end

setter方法中someThingNew的参数已经是retain,也就是说它的retain count是1。

这里的问题是:someThingNew 应该是release 吗?

或者因为someThingsomeThingNew指向同一个对象,而在dealloc方法中someThing一直是release所以someThingNew指向nil

【问题讨论】:

标签: objective-c setter


【解决方案1】:

someThingNew 应该发布吗?

不,因为现在someThingsomeThingNew 指向同一个地址。通过在 dealloc 中释放 someThing (并为安全起见,将其归零,但这是另一个问题),您可以平衡 setter 中的保留。一切正常!*

*旁注:NSString 的实例在 setter 中通常是 copy'd,而不是 retaind,因此即使您不小心将 NSMutableString 传递给它也没关系。

【讨论】:

  • 抱歉,我不小心输入了“r”而不是句号。
【解决方案2】:

每当调用 setter 方法时,都会保留 someThingNew 并释放 someThing。然后将 someThingNew 的新地址存储在 someThing 中,使保留计数为 1。

这将保留在类中,直到对象本身未被释放。一旦调用了 dealloc,someThingNew 的指针就会被释放,从而使保留计数为 0。

【讨论】:

  • 这意味着 [someThing release] 实际上发布了 someThing 和 someThingNew。非常感谢。
【解决方案3】:

您的代码是正确的:如果您想让它成为“强”变量,setter 应该保留该对象。但是您不必释放它:这不是 setter 的职责范围。因此,在您调用 setter 的代码中,您将:

  • 分配要分配的对象;
  • 调用设置器;
  • 当您不再需要它时释放它。

你做得很好,除了字符串通常被复制的事实,因为由于多态性是有效的,指针可能指向一个可变的字符串对象,因此它可能会从一个时刻变为另一个。

示例:

NSAutoreleasePool* pool=[[NSAutoreleasePool alloc]init];
NSString* newString= [[NSMutableString alloc]initWithString: @"Hello"]; // Retain count 1.
[newString autorelease]; // Still 1 as retain count, but it will be decreased
                         // when the pool will be drained.
[object setSomeThing: newString];  // Retain count 2.
[pool drain]; // Retain count 1

在此示例中,您清楚地看到了为什么需要复制对象而不是保留它:它是一个可变字符串,因此可以随时修改。

复制对象

如果你复制对象,那么你调用方法的方式(所以上面的代码)不会改变,它只会改变方法的实现。像这样的:

- (void) setSomeThing:(NSString *) someThingNew
{
     if(someThing!=someThingNew)
     {
         [someThing release];   // Retain count decreased by 1.
         someThing = [someThingNew copy];  // Retain count 1.
     }
 }

 ... ...
 - (void) dealloc
 {
     [someThing release];
     [super dealloc];
 }
@end

【讨论】:

  • 首先我要问两个问题,第一个是这个,第二个是保留和复制之间的区别。你只要一起回答。我真的很想投票给你的答案,但我没有足够的声誉。谢谢你的工作。
  • 复制创建一个不同的对象,它有自己的保留计数。当您创建一个新对象时,它的保留计数为 1。当然,复制的对象将位于与原始对象不同的内存区域中。我添加了一个示例。
  • 谢谢!问题来了:你没有在 dealloc 方法中释放 someThingNew,你的意思是 someThingNew 应该在其他地方释放吗?
  • 在 dealloc someThingNew 中不再存在。创建它并调用 setter 的人应该释放它。
猜你喜欢
  • 2011-04-13
  • 1970-01-01
  • 2010-11-08
  • 2011-07-24
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 2012-09-20
相关资源
最近更新 更多