0

假设我执行以下操作(foo 从某个对象开始):

[foo release];
// STUFF with foo   
[foo retain];

只要我不重新分配 foo,最后我仍然会拥有相同的 foo,对吗?在 //STUFF 期间我不会冒失去 foo 的风险,是吗?

我想我正在确保我对发布的理解是正确的。如果我释放 foo,它实际上不会消失,直到它的所有句柄都消失了。换句话说,foo 必须分配给 //STUFF 中的某个其他对象,或者 foo 必须超出 //STUFF 中的范围(并且可能创建了一个新的 foo)才能获得实际的原始 foo要删除的对象,对吗?

编辑动机:

我想这样做的原因是可以说我有以下 switch 语句:

switch (test)
{
   case 1:
      foo = [A alloc];
      [foo inita];
      break;
   case 2:
      foo =  [B alloc];
      [foo initb];
      break;
   case 3: 
      [foo setupc];
      break;
   case 4:
      f = [D alloc];
      [foo initd];
      break;
}

在切换之前释放 foo 并在结束时保留它是有意义的。除了案例 3​​。所以,我在想如果可以安全地执行我建议的操作,它可能会使代码更简单。

当然,我可以在每个 alloc/init 周围放置一个释放/保留对,但这是很多重复的代码......

A [foo autorelease] 然后保留可能就可以解决问题。

4

4 回答 4

3

如果该代码开头的保留计数foo变为零,它将被删除并停止工作。autorelease如果您想做类似的事情,请使用。release根据文档,在垃圾收集环境中是无操作的 - 也许这就是您的想法?

于 2010-03-05T22:13:50.723 回答
3

不,这就是发生的事情:

-release方法减少保留计数,然后检查它现在是否为零。如果保留计数为零,则-release调用[self dealloc],这会导致对象立即被释放。因此,鉴于您的示例,在发送消息-release之前发送-retain并不是一个好主意,并且可能会使您的应用程序崩溃。

根据您添加的评论,这是编写代码的另一种方法,我认为可以在避免代码重复的同时执行您想要的操作:

Class class = Nil;

// Decide which class (if any) to use...
switch (test)
{
    case 1: class = [A class];  break;
    case 2: class = [B class];  break;
    case 3: class = foo == nil ? Nil : [C class]; break;
    case 4: class = [D class];  break;
}

// If a class was selected, create a new instance 
// and release the previous one...
if (class != Nil)
{
    [foo release];
    foo = [[class alloc] init];
}

请注意,此处不需要 a -retain,因为正如我之前提到的,+alloc将保留计数设置为 1。

于 2010-03-05T22:18:18.680 回答
0

所做的只是减少每个对象都有release的引用计数器。

不过,我不确定你为什么想要release并且retain像你展示的那样。

于 2010-03-05T22:14:20.847 回答
0

是的,在引用计数(非 GC)环境中,您肯定冒“丢失”的风险。STUFF如果您的第一个-release递减foo的引用计数为 0,它将被释放。在这种情况下继续使用foo是冒险进入未定义的行为,您几乎肯定最终会付出代价。也就是说,这里有龙。它可能适用于您(以及您调用的任何其他框架)不分配任何内存的情况下,在此期间覆盖所引用STUFF的已分配实例并且's方法指向的实例不会改变foofoo-deallocfoo的状态除了释放实例变量引用并粉碎那些引用占用的内存等等。在这种情况下,您的代码可能就像foo没有被释放一样工作,但这只是运气。

在垃圾收集的环境中,您是安全的。因为您持有对foothrough的引用STUFF,并且因为-release-retain在 GC 环境中是无操作的,所以foo仍然有效。

于 2010-03-05T22:41:31.573 回答