19

比方說,我有一個循環,返回一串自動釋放的NSData對象...在ARC下,爲循環創建@autoreleasepool還是可取的嗎?

NSData* bigData = ... 
while(some condition) { 
    NSData* smallData = [bigData subdataWithRange:...]; 
    //process smallData 
} 

根據ARC,我應該還是環繞while條件的@autoreleasepool

NSData* bigData = ... 
@autoreleasepool { 
    while(some condition) { 
     NSData* smallData = [bigData subdataWithRange:...]; 
     //process smallData 
    } 
} 

爲什麼我問的原因是我看到的儀器穿過屋頂爲調用dataWith...方法,而不是一個initWith...方法我的NSData對象生活的分配數。當我使用initWith...時,生存分配數量非常少得多。

只要有可能就更喜歡initWith...方法嗎?

回答

13

是的,你應該仍然使用autorelease池時使用方便的方法在一個緊密的循環。所有舊的內存管理規則仍然適用於ARC,編譯器僅僅爲您注入RR。檢查偉大的職位真棒邁克灰!

Link

+0

感謝您的好鏈接! –

+10

Per @ Chuck的回答:@autoreleasepool需要在*循環內部執行任何操作。成語是'while(x)@autoreleasepool {...}',而不是'@autoreleasepool {while(x){...}}'。 – Quuxplusone

+0

這是過度簡化和不正確的。 ARC通常可以優化使用autorelease pool來返回+0對象的方法(這是使用'autorelease'最常用的方法)。 –

7

根據ARC,我應該還是環繞而條件的@autoreleasepool?

是的。自動釋放池仍然存在,並像以前一樣成長和流行。基於TU可見的方法和默認命名約定,編譯器只是在啓用ARC(回顯Logan)時添加併合並必要的保留和釋放操作。

ARC中的執行與手動引用計數幾乎完全相同:自動釋放池堆棧仍然存在。一個不同之處在於,編譯器可能會將引用計數操作的順序與您編寫的方式略有不同(而不是以錯誤的方式),並且可能會省略不必要的保留週期。

只要有可能就更喜歡initWith ...方法嗎?

WRT與自動發佈的同行相比,儘量減少堆增長:是的。情況總是如此。這對於內存非常有限的iOS設備尤其重要。

此例外是當對象可能會避免分配。例如:

NSString * copy = [NSString stringWithString:arg]; 
在這種情況下

copy可以是[[arg retain] autorelease]。請注意,在這種情況下,copy仍然是自動發佈的,但您通常不應該竭盡全力來測試此類優化的存在。注意:這裏最好使用copy = [arg copy] ... [arg release]

另一個好處是,當對象從不自動釋放並且更接近呼叫站點(而不是自動釋放池最終彈出時)時,您的裁判計數不平衡通常會更早捕獲。

大型自動釋放池的性能實際上比大多數人想象的要差得多。如果你可以避免依賴他們(例如使用alloc + init ...+ release),您可以使程序明顯更快。顯式創建自動釋放池很便宜,並且可以幫助最大限度地減少此問題。當分配量很大和/或很多時,儘可能避免使用autorelease,並將這些部分封裝在明確的自動釋放池中。

13

我認爲你的問題是該autorelease池應該去裏面循環。循環在autorelease塊內而不是反過來,累積的對象直到循環結束後纔會被釋放。

+0

我沒想過把'@ autoreleasepool'放到循環中......謝謝你的提示。 –