簡體   English   中英

在將對象添加到集合之前使用自動釋放?

[英]Use autorelease before adding objects to a collection?

我一直在查看StackOverflow上提出的問題,但是在Objective-C中有很多關於內存管理的內容,我找不到我想要的答案。

問題是,在將新創建的對象添加到集合(如NSMutableArray)之前,是否可以(並建議)調用autorelease? 或者我應該在添加后明確地發布它。 (我知道NSMutableArray會保留對象)

這說明了我的問題:

場景A(自動釋放):

- (void) add {
   // array is an instance of NSMutableArray

   MyClass *obj = [[[MyClass alloc] init] autorelease];

   [array addObject:obj];
}

場景B(明確發布):

- (void) add {
   // array is an instance of NSMutableArray

   MyClass *obj = [[MyClass alloc] init];

   [array addObject:obj];

   [obj release];
}

我認為兩者都是正確的,但我不確定,我肯定不知道什么是優先的方式。

Objective-C大師可以對此有所了解嗎?

恕我直言,哪種方式是'正確的'是一個偏好的問題。 我並不反對主張不使用autorelease的響應者,但我更傾向於使用autorelease除非有極其令人信服的理由不這樣做。 我將列出我的理由,你可以決定它們是否適合你的編程風格。

正如查克所指出的,有一個半城市的傳說,使用自動釋放池有一些開銷。 這可能不是事實,這來自於使用Shark.app花費無數個小時來擠出代碼中的最后一點性能。 試圖對此進行優化是“過早優化”領域的深層原因。 如果且僅當Shark.app為您提供了硬數據,這可能是一個問題,您甚至應該考慮查看它。

正如其他人指出的那樣,一個自動釋放的對象“會在稍后發布”。 這意味着他們徘徊在周圍,占據記憶,直到“后來的點”滾動。 對於“大多數”情況,這是在運行循環休眠直到下一個事件(計時器,用戶點擊某些內容等)之前的事件處理過程的底部。

但有時候,你需要盡快擺脫那些臨時物體,而不是以后。 例如,您需要處理一個巨大的,多兆字節的文件,或數據庫中的數萬行。 發生這種情況時,您需要放置一個NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 在一個精心挑選的點,然后是[pool release]; 在底部。 這幾乎總是發生在某種“循環批處理”中,因此它通常位於某個關鍵循環的開始和底部。 同樣,這應該是基於證據的,而不是基於預感的。 Instrument.app的ObjectAlloc是您用來查找這些問題點的方法。

easier to write leak-free programs. 不過,我更喜歡autorelease release主要原因是編寫無泄漏程序容易 circumstances. 簡而言之,如果您選擇使用release路徑,則需要保證情況下最終都會將release發送到obj 雖然這看起來很簡單,但實際上卻很難做到。 舉個例子,舉個例子:

   // array is an instance of NSMutableArray
   MyClass *obj = [[MyClass alloc] init];
   [array addObject:obj];
   // Assume a few more lines of work....
   [obj release];

現在想象一下,出於某種原因,某些東西,巧妙地違反了你的假設,即array是可變的,可能是使用某種方法處理結果的結果,並且包含處理結果的返回數組被創建為NSArray 當您將addObject:發送到該不可變的NSArray ,將拋出異常,並且您永遠不會發送objrelease消息。 或者也許在objalloc d和所需的 release調用之間出現問題,就像你檢查一些條件並立即錯誤地return() ,因為它讓你想到以后必須 release調用。

你剛剛泄露了一個物體。 並且可能已經簽了幾天試圖找出泄漏的地方和原因。 根據經驗,您將花費很多時間查看上面的代碼,確信它不可能是泄漏的來源,因為您非常清楚地發送obj release 然后,幾天之后,你將體驗到只能被描述為宗教頓悟的東西,因為你對問題的原因有所啟發。

考慮autorelease案例:

   // array is an instance of NSMutableArray
   MyClass *obj = [[[MyClass alloc] init] autorelease];
   [array addObject:obj];
   // Assume a few more lines of work....

現在,它不再重要,因為即使在非常不尋常或特殊的角落情況下,它幾乎不可能意外地泄漏obj

兩者都是正確的,並且會像你期望的那樣工作。

我個人更喜歡使用后一種方法,但僅僅因為我喜歡明確何時釋放對象。 通過自動釋放對象,我們所做的只是說“這個對象將在未來的某個任意點發布。” 這意味着你可以將自動釋放的對象放入數組中,銷毀數組,並且對象可能(可能)仍然存在。

使用后一種方法,對象將立即被陣列銷毀(假設沒有其他任何東西出現並在此期間保留它)。 如果我在一個內存受限的環境(比如iPhone)中我需要注意我正在使用多少內存,我將使用后一種方法,因此我沒有那么多的對象揮之不去一個NSAutoreleasePool。 如果內存使用對你來說不是一個大問題(通常也不適合我),那么任何一種方法都是完全可以接受的。

它們都是正確的但B可能是首選,因為它根本沒有開銷。 自動釋放導致自動釋放池負責對象。 這有一個非常小的開銷,當然,它會乘以所涉及的對象數量。

因此,對於一個對象A和B或多或少相同,但絕對不要在有大量對象添加到數組的場景中使用A.

在不同情況下,自動釋放可能會延遲並累積在線程末尾釋放許多對象。 這可能是次優的。 在沒有明確干預的情況下,無論如何都要注意自動釋放​​。 例如,許多getter以這種方式實現:

return [[myObject retain] autorelease];

因此,無論何時調用getter,都會將對象添加到自動釋放池中。

您可以隨時發送autorelease消息,因為在應用程序的消息循環重復之前(即直到所有方法都響應用戶輸入完成執行)之后才會執行該操作。

http://macdevcenter.com/pub/a/mac/2001/07/27/cocoa.html?page=last&x-showcontent=text

你已經alloc了對象,那么你的工作就是在某個時候釋放它。 兩個代碼片段僅以相同,正確的方式工作, autorelease方式可能是較慢的對應方式。

就個人而言,我更喜歡autorelease方式,因為它更容易打字,幾乎從不是瓶頸。

他們都很好。 有些人會因為“開銷”或某些事情而告訴你要避免自動釋放,但事實是,實際上沒有開銷。 繼續進行基准測試並嘗試找到“開銷”。 你避免使用它的唯一原因是像iPhone一樣處於記憶匱乏的境地。 在OS X上,你幾乎擁有無限的內存,所以它不會產生太大的影響。 只需使用最方便的方式。

我更喜歡A(自動釋放)以簡潔和“安全”,正如johne所說的那樣。 它簡化了我的代碼,我從來沒有遇到過它的問題。

也就是說,直到今天:在將塊添加到數組之前,我遇到了自動釋放塊的問題。 請參閱我的stackoverflow問題: [myArray addObject:[[objcBlock copy] autorelease]]在dealloc'ing數組時崩潰 (更新:結果問題在我的代碼中的其他地方,但仍然,自動釋放的行為有細微差別... )

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM