Objective c ObjC:直接分配给属性并释放它有多糟糕?

Objective c ObjC:直接分配给属性并释放它有多糟糕?,objective-c,coding-style,Objective C,Coding Style,我想知道下面的代码对于有经验的objective-C程序员来说有多糟糕 self.request = [[ASIHTTPRequest alloc] initWithURL:url]; [self.request release]; 这绝对不是那么冗长 ASIHTTPRequest *tmp = [[[ASIHTTPRequest alloc] initWithURL:url]; self.request = tmp; [tmp release]; 但我不确定它是否有足够的意义或者不会导致b

我想知道下面的代码对于有经验的objective-C程序员来说有多糟糕

self.request = [[ASIHTTPRequest alloc] initWithURL:url];
[self.request release];
这绝对不是那么冗长

ASIHTTPRequest *tmp = [[[ASIHTTPRequest alloc] initWithURL:url];
self.request = tmp;
[tmp release];
但我不确定它是否有足够的意义或者不会导致bug

你觉得怎么样

更新:
我不想使用自动弹性池,因为我的应用程序将在内存有限的iphone上运行。

当然要使用后者,尽管选择更具描述性的名称而不是
tmp
。您负责发布
tmp
,但您不负责发布
self.request
,至少在给定的上下文中不负责

或者,如果您不介意向自动释放池添加内容,只需执行以下操作:

self.request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];


尽管选择一个更具描述性的名称而不是
tmp
,但一定要选择后者。您负责发布
tmp
,但您不负责发布
self.request
,至少在给定的上下文中不负责

或者,如果您不介意向自动释放池添加内容,只需执行以下操作:

self.request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];

为什么不是这个

self.request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
或者,如果这是您编写的类或有其源代码,请创建一个新的类方法(而不是实例),该方法基本上执行相同的操作(假设
NSURL*
参数):

为什么不是这个

self.request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
或者,如果这是您编写的类或有其源代码,请创建一个新的类方法(而不是实例),该方法基本上执行相同的操作(假设
NSURL*
参数):

更新:我不想使用自动弹性池,因为我的应用程序将在内存有限的iphone上运行

一定要使用自动释放池!Cocoa touch框架本身使用它们;自己制作一两个
自动释放
对象并不会改变全局

没错,苹果警告你不要过度依赖iPhone上的自动释放池,比如在事件分派结束后,在池中耗尽之前放置大量对象,但过度避免自动释放池也会适得其反

没有什么是黑白的;涅磐在天堂

更新:我不想使用自动弹性池,因为我的应用程序将在内存有限的iphone上运行

一定要使用自动释放池!Cocoa touch框架本身使用它们;自己制作一两个
自动释放
对象并不会改变全局

没错,苹果警告你不要过度依赖iPhone上的自动释放池,比如在事件分派结束后,在池中耗尽之前放置大量对象,但过度避免自动释放池也会适得其反


没有什么是黑白的;涅磐在你的记忆中。

你错过的不是冗长的差别,而是记忆管理的差别。

您经常会看到这样的代码:

ASIHTTPRequest * requestTmp = [[[ASIHTTPRequest alloc] initWithURL:url];
self.request = requestTmp;
[requestTmp release];

你应该考虑如果保留的属性发生了什么,旧的在Stter方法中被释放。

  • 这意味着创建新的
    请求
    ,refcount为1
  • self.request=request
    ,现在如果
    setRequest
    看起来像:

    - (void)setRequest:(ASIHTTPRequest*)aReq
    {
        [aReq retain];
        [request release];
        request = aReq;
    }
    
    这意味着对象保留了您传入的
    requestTmp
    ,并释放了旧的。
    requestTmp
    的Refcount现在是2

  • 在此调用之后,您可以释放您创建的原始
    requestTmp
    ,并且您是安全的,因为保留
    requestTmp
    -refcount的对象仍然是1

但是,如果您这样做:

self.request = [[ASIHTTPRequest alloc] initWithURL:url];
[self.request release];
您最终释放了对象保留的
请求
,以供其使用。请注意,您正在释放对象的内部
请求
,在原始情况下,您释放了
tmp
,但对象保留了自己的保留引用


因此,结果与原始代码不同。

您错过的不是详细程度的差异,而是内存管理的差异。

您经常会看到这样的代码:

ASIHTTPRequest * requestTmp = [[[ASIHTTPRequest alloc] initWithURL:url];
self.request = requestTmp;
[requestTmp release];

你应该考虑如果保留的属性发生了什么,旧的在Stter方法中被释放。

  • 这意味着创建新的
    请求
    ,refcount为1
  • self.request=request
    ,现在如果
    setRequest
    看起来像:

    - (void)setRequest:(ASIHTTPRequest*)aReq
    {
        [aReq retain];
        [request release];
        request = aReq;
    }
    
    这意味着对象保留了您传入的
    requestTmp
    ,并释放了旧的。
    requestTmp
    的Refcount现在是2

  • 在此调用之后,您可以释放您创建的原始
    requestTmp
    ,并且您是安全的,因为保留
    requestTmp
    -refcount的对象仍然是1

但是,如果您这样做:

self.request = [[ASIHTTPRequest alloc] initWithURL:url];
[self.request release];
您最终释放了对象保留的
请求
,以供其使用。请注意,您正在释放对象的内部
请求
,在原始情况下,您释放了
tmp
,但对象保留了自己的保留引用


因此,结果与原始代码不同。

我认为在这种情况下,添加到自动释放池没有什么大不了的,因为对象实际上不会被释放。这只是一个保留计数递减(不是免费的),因为(大概)属性分配增加了保留计数。当然,它会被释放。它将在自动释放池排空时释放。如果属性保留请求实例,它将不会被解除分配。使用自动释放池更简洁,但要付出一点点不可察觉的开销;我对术语使用不当。s/已发布/取消分配。我的观点是,将其添加到autorelease池并没有占用本来可以立即释放的内存,因为属性设置程序可能保留了该对象。正在添加到此中的自动释放池