释放并保留

时间:2010-03-05 22:11:17

标签: objective-c release retain

假设我做了以下(foo作为某个对象开始):

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

只要我不重新分配foo,在这结束时我仍然会有同样的foo,对吧?我不会在// STUFF期间冒失去foo的风险吗?

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

编辑动机:

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

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周围放置一个release / retain对,但这是很多复制代码......

[foo autorelease]然后保留可能就是这个伎俩。

4 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分: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];
}

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

答案 2 :(得分:0)

所有release都会减少每个对象所具有的引用计数器。

我不确定你为什么要像你所展示的那样releaseretain

答案 3 :(得分:0)

是的,在参考计数(非GC)环境中STUFF期间,您绝对 冒着“失去”的风险。如果您的第一个-release递减foo的引用计数为0,它将被取消分配。在这种情况下继续使用foo冒险进入未定义的行为,你几乎肯定会付出代价。换句话说,这里有龙。如果您(以及您调用的任何其他框架)在STUFF期间没有分配任何内存,那么可能工作,这会占用foo引用的已分配实例和{/ strong> foo的{​​{1}}方法指向的实例不会更改-dealloc的状态,除非释放实例变量引用并粉碎这些引用占用的内存和等等。在这种情况下,您的代码可能的工作方式就好像foo尚未解除分配,但这只是运气。

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