2013-04-23 87 views
0

我最近在閱讀Advanced Memory Management文檔時偶然發現了自動釋放池塊。該文檔指出:自動釋放池塊

您可以在循環中使用autorelease池塊來在下一次迭代之前處置這些對象。在循環中使用自動釋放池塊有助於減少應用程序的最大內存佔用。[...]任何在autorelease池塊內發送autorelease消息的對象都會在塊的末尾釋放。

那麼塊內創建的對象沒有autorelease調用呢?我假設他們也得到他們的保留計數遞減到0.然後,我的問題是,當方法,在塊內創建的對象將在塊的末尾獲得釋放呼叫時,調用autorelease有什麼意義?

回答

2

一個對象可以通過發送一個-release-autorelease消息來釋放。

隨着-release引用計數立即遞減,這可能導致釋放。

隨着-autorelease延期遞減,以保持一個對象超出它創建的範圍。例如,幫助程序方法-createFoo可能會返回一個自動釋放對象,以便調用者可以使用返回的對象,而不必在從方法返回時立即釋放該對象,也無需擔心由誰負責釋放它。

使用ARC,編譯器會爲您處理所有這些細節。所有你需要知道的是,有時物體會使用autorelease長時間存活。

這種「保活」的行爲有像下面的循環含義:

- (void)foobar 
{ 
    for (/* a long time */) { 
     NSMutableString *s = [NSMutableString string]; 
     // ... 
    } 
} 

NSMutableString+string方法會返回一個自動釋放的對象。這是而不是在循環迭代或方法結束時自動釋放(當然,ARC可以通過查看調用堆棧來做一些聰明的優化,但我們會忽略它)。這意味着當你處於循環體內時,你將獲得無限的內存增長。

需要注意的是,如果我們使用了以下內容:

NSMutableString *s = [[NSMutableString alloc] init]; 

然後ARC將在循環體的末尾插入release調用和字符串將被立即釋放。

要解決的第一個例子中的無限存儲的增長,你定義一個明確的自動釋放池:

- (void)foobar 
{ 
    for (/* a long time */) { 
     @autoreleasepool { 
      NSMutableString *s = [NSMutableString string]; 
      // ... 
     } 
    } 
} 

現在,每次循環後,自動釋放池被銷燬並自動釋放任何對象游泳池內(包括我們的字符串)將立即釋放。

所以這一切都取決於您調用的方法的種類以及它們是否返回自動釋放對象。「

+0

」現在,在循環的每次迭代之後,autorelease池將被銷燬,並且任何在池中自動釋放的對象(包括我們的字符串)都將立即釋放。「那麼如果他們不是在內部自動釋放呢?無論如何,它們是否不會在autorelease塊的末尾被釋放,因爲它們的壽命不能超越塊?然後我的問題仍然存在:爲什麼我們需要autorelease調用,當對象在塊的末尾被釋放時? – Teo 2013-04-23 07:37:33

+1

自動釋放池只釋放自動釋放的對象。對於非自動釋放對象,編譯器將在適當的位置插入顯式釋放調用,以便在自動釋放池結束之前釋放它們。 – 2013-04-23 07:42:53

+1

以防萬一你錯了:在我的文章的第一個代碼塊中,沒有自動釋放池。在方法返回時,不會釋放方法或循環內部創建的任何自動釋放對象。他們將在稍後發佈。在大多數UI代碼中,會爲runloop的每次迭代創建一個更高級的自動釋放池。但是如果你有一個緊密的循環,你必須創建你自己的以避免創建太多的對象。 – 2013-04-23 08:00:35