使用Objective-C Cocoa,我们正在使用半自动引用计数内存管理。为对象分配内存,保留对象或在对象上调用方法时,保留计数(引用计数)会增加1.在对象上调用release
时,它会将保留计数递减1。当在一个对象上调用autorelease
时,release
将在将来的某个时刻在对象上被调用(在主运行循环期间,当你自己的代码没有执行时,所以它不会从你的下拉引用该引用)试图使用它)。当保留计数达到0时,可以释放该对象。
一般情况下,如果你的对象上调用retain
,你信令的利益在里面,当你不再感兴趣的对象,你有责任在某些时候作出release
或autorelease
通话。同样,如果您在对象上调用alloc
或copy
方法,则表明您对该对象感兴趣,并且必须将其与匹配的某个位置的release
或autorelease
相匹配。
这个环节几乎涵盖准则苹果使用(你应该使用)的内存管理:Simple rules for memory management in Cocoa
让我们通过代码逐行:
ClassOne *pointer = [[ClassOne alloc]init];
pointer
点到一个新分配的ClassOne对象,保留计数为1,因为我们对它调用了alloc。我们有责任在未来的某个时间拨打release
或autorelease
pointer
。
ClassTwo *foo = [[ClassTwo alloc]init], *foo2;
foo
指向一个新分配ClassTwo对象,为1的保留计数,因为我们调用它的alloc。我们有责任在的某个时间点拨打release
或autorelease
。
foo2
现在没有指出任何特别的东西。这是不安全的使用。
foo2 = [foo add: pointer];
pointer
已添加到foo
(这意味着什么,我们不知道实现)。 foo
可能在pointer
上调用retain
来表示它对其的兴趣,并将其添加为字段,或者它可能已将pointer
添加到集合中(在这种情况下,集合有责任在添加对象时调用retain
,并且release
当一个对象被删除)。无论如何,它不会影响我们的代码块,所以我们不在乎发生了什么事情
此方法返回的引用本身可能是pointer
本身,或者它可能是pointer
的自动发布副本;我们无法访问API或实现来告诉我们哪一个。
在这两种情况下,我们都没有责任在此对象上调用release
。如果该方法的名称中含有copy
,或者如果我们在返回的引用(如foo2 = [[foo add:pointer] retain];
)上调用了retain
,则保留计数将增加1,并且我们有责任调用release
或autorelease
。
[foo release];
通过foo
引用的对象已被释放,这意味着它的保留计数已递减1。在这个例子中,这对与alloc
电话,我们在第2行作出,所以保留计数将降至0,使foo
有资格被释放。一般来说,我们并不在乎对象是否已经被释放;否则,我们并不关心对象是否被释放。我们只需确保我们配对的电话号码与或autorelease
呼叫的号码相同即可呼叫alloc
,copy
或retain
。如果我们随时注册一个对象的兴趣,我们有责任释放我们的兴趣,否则我们会有内存泄漏。
foo = foo2;
foo
现在指向由foo2
引用同一个对象。记住,当我们得到foo2
时,我们还没有调用alloc
或copy
方法,我们也没有通过调用retain
来注册它的兴趣。由于我们没有责任拨打foo2
致电release
,因此我们没有责任致电 foo
。
[pointer release];
pointer
的保留计数已被1.本递减可能带来其保留计数为0与否,这取决于它的时候我们增加了它什么foo
没有。不过,我们不在乎;我们已完成对pointer
的责任,拨打电话release
即可与我们在开始时致电alloc
的电话相匹配。虽然pointer
可能在这次调用之后仍然存在,但是我们不能做出这样的假设,并且试图对先前由指针引用的对象做任何事情都是错误的(尽管我们可以将pointer
更改为指向其他任何东西)。
[foo release];
如果此代码的作者一直关注苹果的内存管理公约,那么这是不必要的。我们没有责任在foo
或foo2
上拨打release
(他们指向相同的对象,请记住)。这不会导致代码破坏;调用nil
引用中的任何内容本质上都是空操作。但是,任何人查看代码可能会造成混淆。
现在,此代码的作者可能已经打破了内存管理约定。他可能会在add
呼叫中返回pointer
的副本,而不会调用autorelease
,在这种情况下,呼叫方会负责呼叫release
。这是一种非常糟糕的形式,如果您遇到违反内存管理约定的代码,请记录您使用它的方式以及它如何打破惯例以避免将来混淆。
这些类的类名是什么? – 2009-02-09 19:26:37
顺便说一下,我不确定这是否是在匿名代码或什么的过程中产生的,但是由于代码只有七行,所以代码很混乱。 – Chuck 2009-02-09 19:40:55