Iphone 用Cocoa和Objective-C理解参考计数

Iphone 用Cocoa和Objective-C理解参考计数,iphone,objective-c,cocoa,memory,Iphone,Objective C,Cocoa,Memory,我刚刚开始了解Objective-C和Cocoa,以期使用iPhone SDK。我对C的malloc和free概念相当满意,但Cocoa的引用计数方案让我相当困惑。有人告诉我,一旦你理解了它,它就非常优雅了,但我还没有渡过难关 发布、保留和自动释放是如何工作的?它们的使用有哪些约定 (或者如果没有,你读了什么帮助你得到了它?Objective-C使用,这意味着每个对象都有一个引用计数。创建对象时,其引用计数为“1”。简单地说,当一个对象被引用(即存储在某处)时,它会被“保留”,这意味着它的引用计

我刚刚开始了解Objective-C和Cocoa,以期使用iPhone SDK。我对C的
malloc
free
概念相当满意,但Cocoa的引用计数方案让我相当困惑。有人告诉我,一旦你理解了它,它就非常优雅了,但我还没有渡过难关

发布
保留
自动释放
是如何工作的?它们的使用有哪些约定

(或者如果没有,你读了什么帮助你得到了它?

Objective-C使用,这意味着每个对象都有一个引用计数。创建对象时,其引用计数为“1”。简单地说,当一个对象被引用(即存储在某处)时,它会被“保留”,这意味着它的引用计数会增加1。当一个对象不再需要时,它将被“释放”,这意味着它的引用计数将减少1

当对象的引用计数为0时,该对象将被释放。这是基本的参考计数

对于某些语言,引用会自动增加和减少,但objective-c不是这些语言之一。因此,程序员负责保留和释放

编写方法的典型方法是:

id myVar = [someObject someMessage];
.... do something ....;
[myVar release];
return someValue;
需要记住在代码中释放任何获取的资源的问题既繁琐又容易出错。Objective-C引入了另一个概念,旨在使这更容易实现:自动释放池。自动释放池是安装在每个线程上的特殊对象。如果您查找NSAutoreleasePool,它们是一个相当简单的类

当对象收到发送给它的“autorelease”消息时,该对象将查找当前线程堆栈上的任何autorelease池。它将把对象作为对象添加到列表中,以便在将来的某个时刻向其发送“release”消息,这通常是在池本身被释放时

根据上面的代码,您可以将其改写为更简短、更易于阅读的代码,方法是:

id myVar = [[someObject someMessage] autorelease];
... do something ...;
return someValue;
因为对象是自动释放的,所以我们不再需要显式地对其调用“release”。这是因为我们知道一些自动释放池稍后会为我们做这件事

希望这能有所帮助。维基百科的这篇文章在引用计数方面做得很好。有关的更多信息。还请注意,如果您是为Mac OS X 10.5及更高版本构建的,您可以告诉Xcode在启用垃圾收集的情况下构建,这样您就可以完全忽略保留/释放/自动释放。

Objective-C使用,这意味着每个对象都有一个引用计数。创建对象时,其引用计数为“1”。简单地说,当一个对象被引用(即存储在某处)时,它会被“保留”,这意味着它的引用计数会增加1。当一个对象不再需要时,它将被“释放”,这意味着它的引用计数将减少1

当对象的引用计数为0时,该对象将被释放。这是基本的参考计数

对于某些语言,引用会自动增加和减少,但objective-c不是这些语言之一。因此,程序员负责保留和释放

编写方法的典型方法是:

id myVar = [someObject someMessage];
.... do something ....;
[myVar release];
return someValue;
需要记住在代码中释放任何获取的资源的问题既繁琐又容易出错。Objective-C引入了另一个概念,旨在使这更容易实现:自动释放池。自动释放池是安装在每个线程上的特殊对象。如果您查找NSAutoreleasePool,它们是一个相当简单的类

当对象收到发送给它的“autorelease”消息时,该对象将查找当前线程堆栈上的任何autorelease池。它将把对象作为对象添加到列表中,以便在将来的某个时刻向其发送“release”消息,这通常是在池本身被释放时

根据上面的代码,您可以将其改写为更简短、更易于阅读的代码,方法是:

id myVar = [[someObject someMessage] autorelease];
... do something ...;
return someValue;
因为对象是自动释放的,所以我们不再需要显式地对其调用“release”。这是因为我们知道一些自动释放池稍后会为我们做这件事

希望这能有所帮助。维基百科的这篇文章在引用计数方面做得很好。有关的更多信息。另外请注意,如果您是为Mac OS X 10.5及更高版本构建,您可以告诉Xcode在构建时启用垃圾收集功能,这样您就可以完全忽略保留/释放/自动释放。

Joshua(#6591)-Mac OS X 10.5中的垃圾收集功能看起来很酷,但在iPhone上不可用(或者,如果你想让你的应用程序在10.5版本之前的Mac OS X上运行)

此外,如果您正在编写一个库或一些可能被重用的东西,使用GC模式会将任何使用该代码的人锁定为也使用GC模式,因此据我所知,任何试图编写可广泛重用代码的人都倾向于手动管理内存。

Joshua(#6591)-Mac OS X 10.5中的垃圾收集功能看起来很酷,但iPhone不支持(或者如果你想让你的应用程序运行在Mac OS X 10.5之前的版本上)


此外,如果您正在编写一个库或一些可能被重用的东西,使用GC模式会将任何使用该代码的人锁定为也使用GC模式,因此据我所知,任何试图编写可广泛重用代码的人都倾向于手动管理内存。

NilObject的答案是一个良好的开端。下面是一些与手动模式相关的补充信息内存管理(iPhone上需要)

如果您个人
alloc/init
一个对象,它的引用计数为1。当不再需要它时,您负责在它之后进行清理,方法是调用
[foo release]
[foo autorelease]
.release会立即清理该对象,而autorelease会将该对象添加到autorelease池中,该池稍后会自动释放该对象

自动释放主要适用于以下情况:
NSString* s = [NSString stringWithString:@"Hello World"];
- (NSString*)createHelloWorldString
{
    NSString* s = [[NSString alloc] initWithString:@"Hello World"];

    // Now what?  We want to return s, but we've upped its reference count.
    // The caller shouldn't be responsible for releasing it, since we're the
    // ones that created it.  If we call release, however, the reference 
    // count will hit zero and bad memory will be returned to the caller.  
    // The answer is to call autorelease before returning the string.  By 
    // explicitly calling autorelease, we pass the responsibility for
    // releasing the string on to the thread's NSAutoreleasePool, which will
    // happen at some later time.  The consequence is that the returned string 
    // will still be valid for the caller of this function.
    return [s autorelease];
}
-(void)getBar {
    return @"bar";
}
NSString *foo = [self getBar]; // still no need to retain or release