我是编码新手并尝试使用Objective-C加快速度.碰到了一些我不明白的代码.我希望有人可以为我澄清一下.在下面的例子中,我不确定*foo2是如何工作的以及为什么它没有被释放?
ClassOne *pointer = [[ClassOne alloc]init]; ClassTwo *foo = [[ClassTwo alloc]init], *foo2; foo2 = [foo add: pointer]; [foo release]; foo = foo2 [pointer release]; [foo release];
小智.. 22
使用Objective-C Cocoa,我们正在使用半自动引用计数内存管理.为对象分配内存,保留对象或copy
在对象上调用方法时,保留计数(引用计数)增加1.当调用release
对象时,它会将保留计数减1.在调用autorelease
一个对象时,release
将来会在某个时刻调用该对象(在主运行循环期间,当你自己的代码都没有执行时,所以它不会从你下面拉出引用,因为你是试图使用它).当保留计数达到0时,可以取消分配对象.
一般来说,如果你正在调用retain
某个对象,那么就表明你对它感兴趣,并且当你不再对该对象感兴趣时,你有责任在某个时刻打电话release
或autorelease
打电话.同样,如果您在某个对象上调用alloc
或使用某个copy
方法,则表示您对该对象感兴趣,并且必须将其与该行release
或autorelease
某个地方相匹配.
这个链接几乎涵盖了Apple使用(并且你应该使用)内存管理的指导原则: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
对foo
在未来的某一时刻.
foo2
现在并没有特别指出任何事情.这是不安全的使用.
foo2 = [foo add: pointer];
pointer
已被添加到foo
(无论这意味着什么;我们不知道实现). foo
可能已经调用retain
上pointer
以通知它的利益在里面,并将其添加为一个字段,或者可能添加pointer
到一个集合(在这种情况下,它收集的责任来调用retain
它添加一个对象时,和release
当一个对象被删除).在任何情况下,它都不会影响我们的代码块,因此我们不关心引擎盖下发生了什么
此方法返回的引用可能是pointer
自身,也可能是自动释放的副本pointer
; 我们无权访问API或实现告诉我们哪个.
无论哪种情况,我们都有责任呼吁release
这个对象.如果方法有copy
名称,或者我们已经调用retain
了返回的引用(例如foo2 = [[foo add:pointer] retain];
),则保留计数将增加1,我们有责任调用release
或autorelease
使用它.
[foo release];
引用的对象foo
已被释放,这意味着它的保留计数已减少1.对于此示例,这与alloc
我们在第2行中进行的调用配对,因此保留计数将降为0,从而使得有foo
资格被释放.
但是,一般而言,我们并不关心对象是否已被解除分配; 我们只需要确保我们配对的任何alloc
,copy
或retain
电话与相同数量的release
或autorelease
来电.如果我们在任何时候注册对象的兴趣,我们有责任释放我们的兴趣,否则我们将有内存泄漏.
foo = foo2;
foo
现在指向引用的同一个对象foo2
.记住,当我们得到时,我们没有调用alloc
或者copy
方法foo2
,也没有通过调用注册它的兴趣retain
.由于我们没有有责任呼吁release
上foo2
,我们没有责任来调用release
上foo
.
[pointer release];
pointer
保留计数已经减少了1.这可能会使其保留计数为0或者不是,这取决于foo
我们添加它时的保留计数.不过,我们并不关心; 我们已经完成了我们的责任pointer
,呼吁release
它与alloc
我们在开始时的电话相匹配.尽管pointer
在这次调用之后可能仍然存在,但是我们无法做出这样的假设,并且尝试对之前由指针引用的对象做任何事情都是错误的(尽管我们可以改变pointer
为指向别的东西).
[foo release];
如果此代码的作者一直遵循Apple的内存管理约定,那么这是不必要的.我们没有责任去呼吁release
对foo
或者foo2
(它们指向同一个对象,记住).这不会导致代码中断; 在nil
引用上调用任何东西本质上都是一个无操作.但是,它可能会导致任何人审查代码时出现混淆.
现在,此代码的作者可能已经破坏了内存管理约定.他可能已经使该add
调用返回了一个副本而pointer
没有调用autorelease
它,在这种情况下,它使调用者负责调用release
它.这是非常糟糕的形式,如果您应该遇到破坏内存管理约定的代码,请记录您使用它的位置以及它如何破坏约定以避免将来出现混淆.
使用Objective-C Cocoa,我们正在使用半自动引用计数内存管理.为对象分配内存,保留对象或copy
在对象上调用方法时,保留计数(引用计数)增加1.当调用release
对象时,它会将保留计数减1.在调用autorelease
一个对象时,release
将来会在某个时刻调用该对象(在主运行循环期间,当你自己的代码都没有执行时,所以它不会从你下面拉出引用,因为你是试图使用它).当保留计数达到0时,可以取消分配对象.
一般来说,如果你正在调用retain
某个对象,那么就表明你对它感兴趣,并且当你不再对该对象感兴趣时,你有责任在某个时刻打电话release
或autorelease
打电话.同样,如果您在某个对象上调用alloc
或使用某个copy
方法,则表示您对该对象感兴趣,并且必须将其与该行release
或autorelease
某个地方相匹配.
这个链接几乎涵盖了Apple使用(并且你应该使用)内存管理的指导原则: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
对foo
在未来的某一时刻.
foo2
现在并没有特别指出任何事情.这是不安全的使用.
foo2 = [foo add: pointer];
pointer
已被添加到foo
(无论这意味着什么;我们不知道实现). foo
可能已经调用retain
上pointer
以通知它的利益在里面,并将其添加为一个字段,或者可能添加pointer
到一个集合(在这种情况下,它收集的责任来调用retain
它添加一个对象时,和release
当一个对象被删除).在任何情况下,它都不会影响我们的代码块,因此我们不关心引擎盖下发生了什么
此方法返回的引用可能是pointer
自身,也可能是自动释放的副本pointer
; 我们无权访问API或实现告诉我们哪个.
无论哪种情况,我们都有责任呼吁release
这个对象.如果方法有copy
名称,或者我们已经调用retain
了返回的引用(例如foo2 = [[foo add:pointer] retain];
),则保留计数将增加1,我们有责任调用release
或autorelease
使用它.
[foo release];
引用的对象foo
已被释放,这意味着它的保留计数已减少1.对于此示例,这与alloc
我们在第2行中进行的调用配对,因此保留计数将降为0,从而使得有foo
资格被释放.
但是,一般而言,我们并不关心对象是否已被解除分配; 我们只需要确保我们配对的任何alloc
,copy
或retain
电话与相同数量的release
或autorelease
来电.如果我们在任何时候注册对象的兴趣,我们有责任释放我们的兴趣,否则我们将有内存泄漏.
foo = foo2;
foo
现在指向引用的同一个对象foo2
.记住,当我们得到时,我们没有调用alloc
或者copy
方法foo2
,也没有通过调用注册它的兴趣retain
.由于我们没有有责任呼吁release
上foo2
,我们没有责任来调用release
上foo
.
[pointer release];
pointer
保留计数已经减少了1.这可能会使其保留计数为0或者不是,这取决于foo
我们添加它时的保留计数.不过,我们并不关心; 我们已经完成了我们的责任pointer
,呼吁release
它与alloc
我们在开始时的电话相匹配.尽管pointer
在这次调用之后可能仍然存在,但是我们无法做出这样的假设,并且尝试对之前由指针引用的对象做任何事情都是错误的(尽管我们可以改变pointer
为指向别的东西).
[foo release];
如果此代码的作者一直遵循Apple的内存管理约定,那么这是不必要的.我们没有责任去呼吁release
对foo
或者foo2
(它们指向同一个对象,记住).这不会导致代码中断; 在nil
引用上调用任何东西本质上都是一个无操作.但是,它可能会导致任何人审查代码时出现混淆.
现在,此代码的作者可能已经破坏了内存管理约定.他可能已经使该add
调用返回了一个副本而pointer
没有调用autorelease
它,在这种情况下,它使调用者负责调用release
它.这是非常糟糕的形式,如果您应该遇到破坏内存管理约定的代码,请记录您使用它的位置以及它如何破坏约定以避免将来出现混淆.