【问题标题】:Releasing local variables before return?在返回之前释放局部变量?
【发布时间】:2011-01-18 01:09:51
【问题描述】:

在 Objective-c 中,我知道您需要释放您初始化/保留/复制的任何内容。我需要在return 声明之前这样做吗?我想了解明确调用release 而不是使用autorelease

-(void) someMethod
{
  AnotherClass* ac = [[AnotherClass alloc] init];
  if([ac somethingHappens]){
    // Do I need to release ac here?
    return;
  }
  [ac doSomethingElse];
  [ac release];
}

谢谢!

【问题讨论】:

  • 在上面的代码中有多个返回路径是不好的做法,一个显式的,一个隐式的。你应该把 return 移到 [release] 下面,想象一下很多 if() 语句,每个都做了一个 return,那是很多重复的代码。
  • 为什么这是不好的做法,因为它很难遵循?似乎遵循一堆 if 逻辑可能同样复杂。
  • 当你有 30 个地方需要复制并通过发布代码块时,它是不可维护的,当你添加一个必须 [release] 的东西时,你现在必须更新 30 个地方.它违反了 DRY 原则(不要重复自己)。如果您有返回值,更好的做法是在逻辑中设置返回值,然后在函数底部返回该值,就在 [release] 块的单点之后。

标签: objective-c release local-variables


【解决方案1】:

是的,你需要释放你的变量,但是你从方法中退出。

这很简单:当您初始化某些东西时,保留计数会增加。当您释放时,它会减少。当它达到零时,它会自动释放(释放)。

在上面的代码中,您初始化了变量,但如果它遵循返回路径,那么变量的保留计数永远不会为零,因此永远不会被释放。

【讨论】:

  • 其实不是当你init某事,而是当你alloc某事。如果您的init 方法没有调用[super init],则保留计数仍为1。
  • @Stephen,谢谢,这就是我需要知道的。我现在也明白了。
  • @Sam Washburn:您在编辑问题之前是正确的。 NSObject 的alloc 方法的文档明确声明它在返回之前保留对象。
【解决方案2】:

假设有一个像下面这样分配的局部变量

NSString *placeHolder = [NSString stringWithFormat:@"%@ %@",[someObject value1], [someObject value2]];

现在将此变量传递给对象定义的方法,例如 UISearchBar 对象的 setPlaceholder

[self.theSearchBar setPlaceholder:placeHolder];

如何正确释放分配的字符串'placeHolder'?

如果你想自动释放它:

NSString *placeHolder = [[NSString stringWithFormat:@"%@ %@",[someObject value1], [someObject value2]] autorelease];

您的代码将因 bad_exc_access 而失败

如果您想在传递到其他地方后释放变量,例如

[self.theSearchBar setPlaceholder:placeHolder];
[placeHolder release];

也会抛出运行时异常。

那怎么了?

问题是保留计数。 UISearchBar 对象尚未分配,因此如果您释放或自动释放该对象引用的此类变量,则保留计数仍然相同

NSLog(@"Retain count before assign to refer other object %d", [placeHolder retainCount]);
[self.theSearchBar setPlaceholder:placeHolder];
NSLog(@"Retain count after referencing %d", [placeHolder retainCount]);

那么,如何处理呢?

试试下面的方法

[placeHolder retain]; // retainCount +1
[self.theSearchBar setPlaceholder:placeHolder];
[placeHolder release]; // retainCount -1

我们做了什么?现在让我们看看保留计数

NSLog(@"Retain count before doing retain %d", [placeHolder retainCount]);
[placeHolder retain]; // retainCount +1
NSLog(@"Retain count after retaining it %d", [placeHolder retainCount]);

因此,我们在将保留计数分配(被引用)给某个对象之前增加了保留计数,然后 - 之后 - 我们在 本地 释放该变量。

就是这样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-17
    • 2014-11-25
    • 2013-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-07
    • 1970-01-01
    相关资源
    最近更新 更多