2

當實例方法返回一個使用便利構造函數初始化的值時,是否需要保留該對象,然後在返回中自動釋放,以便當便利構造函數的autorelease發生時,它不會不要刪除對象。通過「便利構造函數」初始化的返回對象

這個版本會在調用代碼之前描述並取得保留或所有權嗎?

- (NSStringMutable *)test { 
    NSMutableString *description = [NSMutableString stringWithString:@"Test Value"]; 
    return description; 
} 

還是應該是這樣?

- (NSStringMutable *)test { 
    NSMutableString *description = [NSMutableString stringWithString:@"Test Value"]; 
    [description retain];        
    return [description autorelease]; 
} 

長途區號:

NSMutableString *testVar = [[NSMutableString alloc] initWithString:[object description]]; 

回答

9

不,你應該是罰款:

- (NSStringMutable *)test 
{ 
    return [NSMutableString stringWithString:@"Test Value"]; 
} 

這將使對象爲1的保留計數,並會在自動釋放池。

自動釋放池在特定時間耗盡 - 它不像垃圾收集器。如果你正在實現一個事件處理程序(就像一個按鈕被點擊的處理程序),當你從事件處理代碼返回時,autorelease池會被框架耗盡。

如果您用過這樣的:

- (NSStringMutable *)test 
{ 
    NSMutableString *description = [NSMutableString stringWithString:@"Test Value"]; 
    [description retain];                
    return [description autorelease]; 
} 

...那麼對象將有一個保留的2計數和將在自動釋放池兩次,實際上會以同樣的方式表現爲在前面的代碼示例。

+0

+1這回答了問題 – Abizern 2009-08-12 15:11:08

+2

你是對的,但儘量避免談論保留計數,他們是一個紅鯡魚 - 沒有保證NSMutableString會返回一個自動釋放對象,只是它返回一個可變字符串,你目前不擁有。您可以將結果安全返回到您的調用僅僅是因爲內存managemnt規則明確地說:「這方法也可以安全地將對象返回到它的調用」。 2009-08-13 03:14:37

+2

這是一個很好的觀點。我發現從保留數量的角度來思考解釋事物是很方便的。你是對的 - 你知道的只是stringWithString返回一個其他人擁有的對象。在這種情況下,由於NSMutableString實際上分配了該對象,因此NSMutableString負責釋放它。 雖然我覺得這些便利構造函數(非init構造函數)通常會返回自動釋放對象。如果我遇到不以這種方式行事的人,我會感到驚訝。 – 2009-08-14 19:44:32

0

不,你可以簡單地返回自動釋放的價值。原因是autorelease不是變量本身的函數,它是autorelease池的一個函數,除非你自己創建一個函數,它通常由運行循環管理。

0

您已經接近第二個,但您並不需要保留您在此處討論的案例,實際上不需要自己調用autorelease。

這是有效的,因爲stringWithString就已經返回自動釋放的對象:創建使用Objective-C,如果你在呼喚一個便捷構造對象時

- (NSStringMutable *)test 
{ 
    return [NSMutableString stringWithString:@"Test Value"];   
} 

一般(沒有要求alloc和INIT)的返回值總是自動釋放,所以stringWithString返回一個自動釋放的對象,你可以返回。

1

您可以返回它。這是autorelease的主要目的之一。除非你已經建立了自己的自動釋放池,否則在下一次運行事件循環之前,池不會被排空。 memory management programming guide詳細解釋了所有這些 - 你應該閱讀,直到你感覺舒服。

注意:如果這個不是安全,autorelease池會因爲一些離奇的原因而提早耗盡,給它兩個保留和兩個autoreleases沒有什麼區別。這些數字仍然是平衡的,所以它仍然會在某個時候被釋放。

1

我已經投票了正確的答案,我加入這個作爲一種風格注:

調用代碼是行不通的,因爲它是調用[object description]時,應該調用[object test]

除非您真的想更改字符串,否則不需要返回可變字符串。我個人嘗試儘量減少我編寫的代碼中的可變性,因爲我覺得維護狀態更改最小的程序更容易。你只是返回一個描述,所以我不認爲它需要變化。 我知道這僅僅是一些示例代碼,所以也許我太挑剔

你可以重寫此爲:

-(NSString *)description { 
    // Just return a static NSString. No need to worry about memory management. 
    return @"Test Value"; 
} 

如果你希望能夠改變這個值返回的字符串在您的調用代碼:

NSMutableString *testVar = [[NSMutableString alloc]initWithString:[object description]]; 

既然你已經呼籲該字符串頁頭,你擁有它,並負責在將來的某一天釋放它。

或者,你可以用我最喜歡的碼位的一個:

NSMutableString *testVar = [[object description] mutableCopy]; 

這將返回甚至不可變對象的可變副本(如果它符合NSMutableCopying協議,當然)。並且您需要在某個階段發送[testVar release]

而且,以配合這作爲一個實際的回答你的問題:如果你發送ALLOC複製mutableCopy,或保留到一個對象,那麼你就擁有該對象,並負責發送它是一個版本消息。你可以假設其他東西都返回一個自動釋放對象。

同樣,我知道這只是示例代碼的快速位,你問一個問題,但如果你堅持,你已經得到了大部分的排序內存管理問題,上述規則。在你的第一個例子中,你沒有發送這些消息,所以你不需要自己釋放任何內存。但是,您的呼叫代碼中有一個alloc,因此您擁有testVar,您需要將其釋放。

+0

感謝您的意見。我不知道mutableCopy。你是對的,這只是我的問題的一個例子。感謝您的闡述。我對目標c相當陌生,我甚至沒有返回一個可以傳遞給NSMutableString的initWithString的NSString。謝謝(你的)信息。 – Brian 2009-08-12 17:09:56