假设我做了以下(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]然后保留可能就是这个伎俩。
答案 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
都会减少每个对象所具有的引用计数器。
我不确定你为什么要像你所展示的那样release
和retain
。
答案 3 :(得分:0)
是的,在参考计数(非GC)环境中STUFF
期间,您绝对 冒着“失去”的风险。如果您的第一个-release
递减foo
的引用计数为0,它将被取消分配。在这种情况下继续使用foo
冒险进入未定义的行为,你几乎肯定会付出代价。换句话说,这里有龙。如果您(以及您调用的任何其他框架)在STUFF
期间没有分配任何内存,那么可能工作,这会占用foo
引用的已分配实例和{/ strong> foo
的{{1}}方法指向的实例不会更改-dealloc
的状态,除非释放实例变量引用并粉碎这些引用占用的内存和等等。在这种情况下,您的代码可能的工作方式就好像foo
尚未解除分配,但这只是运气。
在垃圾收集环境中,您是安全的。由于您持有foo
到foo
的引用,并且因为STUFF
和-release
在GC环境中是无操作,-retain
仍然有效。