2011-02-28 54 views
6

我發現一個Objective-C/cocoa框架的例子有以下代碼。Objective-C/cocoa框架中NSAutoreleasePool的神奇之處是什麼?

int main() 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    // Create an array 
    NSArray *month = [NSArray arrayWithObjects:@ ... nill]; 

    [pool drain]; 
} 
  • Q1:什麼是這背後的魔力(爲什麼我需要有NSAutoreleasePool代碼?)? NSAutoreleasePoolpool drain塊之間發生了什麼魔術?我看到我自己並不需要發佈*month。這是因爲它在NSAutoreleasePoolpool drain區塊內嗎? Q2:使用Xcode,我已經獲得了main()函數。在這種情況下,我如何使用NSAutoreleasePoolpool drain

例如:

int main(int argc, char *argv[]) 
{ 
    //NSAutoreleasePool *pool = [[[NSAutoreleasePool] alloc] init]; 
    return NSApplicationMain(argc, (const char **) argv); 
} 

回答

4

Q1:神奇的是NSObject -autorelease實例方法調用NSAutoreleasePool + addObject:class方法。 NSObject實例彙集在當前的NSAutoreleasePool實例中。 NSAutoreleasePool -drain實例方法調用池實例的發佈方法。

它與Apple和GNUstep的Cocoa實現不完全相同,但它是相似的。

我不知道爲什麼一個月不被釋放,應當由排水釋放。 Q2:你可以在任何你想使用的地方使用NSAutoreleasePool。實例化一個NSAutoreleasePool意味着當前池將被新實例改變。排水將回到當前池到先前的實例。

除了NSApplicationMain永遠不會返回。它調用退出函數來退出應用程序並終止進程。

+0

我沒有直接調用-autorelease。這是否被隱含地稱爲? – prosseek 2011-02-28 04:52:02

+0

是的@Prairiedogg說。 arrayWithObjects在內部調用autorelease。 – 2011-02-28 04:54:50

0

我是相當新的目標C,但讓我這個給一條縫:

自動釋放池是目標C來處理垃圾的方式採用比手動更簡單的方式進行採集。

它通過計數引用來完成此操作,或者在這種情況下每次調用「保留」或「釋放」。

所以,如果你有一個對象的實例中的「一」,你可以這樣做:

這使得它變成了AutoreleasePool: [a autorelease];

這會告訴你想堅持的自動釋放池給它一段時間: [a retain];

現在你調用[pool drain],它會注意到你有一個對a的引用,並且它不會釋放內存。但是,如果您稍後調用[a release],則下一次調用[pool drain]時,它會看到沒有其他引用,並取消分配內存。

我有一個鬼鬼祟祟的懷疑,我剛纔談到自己在圈而不做一大堆的道理,但這裏是引用計數的維基百科文章:http://en.wikipedia.org/wiki/Reference_counting

+0

自動釋放不同於垃圾收集; GC不需要額外的代碼。 「保留」和「釋放」與自動釋放池無關; 'autorelease'將接收者添加到自動釋放池堆棧中最頂層的自動釋放池中,以便當該池被耗盡時,池將向其發送一個「釋放」消息。 – 2011-02-28 04:55:00

+0

基本閱讀:http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/ – 2011-02-28 04:55:37

+1

這很接近,但在一些重要細節上是錯誤的。例如,說「(autorelease池)對引用進行計數」或「[retain]」告訴autorelease池想要保留它「是不正確的。引用計數的基本操作是「保留」和「釋放」;他們根本不涉及autorelease池。 'autorelease'只是延遲釋放調用的一種方式,直到後來(特別是直到下一個'[pool drain]')。閱讀Peter Hosey提供的參考,然後再讀一遍:-) – 2011-02-28 06:39:25

3

Q1:

你不需要在您給出的示例中釋放month實例,因爲您調用的NSArray類方法(arrayWithObjects:)將返回一個自動釋放的實例。按照Cocoa中的約定,以該類名稱開頭的類方法將返回該類的自動釋放實例。這些示例:

[NSString stringWithFormat:@"Holla %@", @"back girl!", nil]; 
[NSArray arrayWithObjects:@"Holla", @"back", @"girl!", nil]; 

這兩個都會返回它們各自的自動釋放對象的實例。

+0

然後,我認爲我不需要'NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];'code as'NSArray * month = [NSArray arrayWithObjects:@ ... nill];'無論如何都會自動釋放。這是對的嗎? – prosseek 2011-02-28 04:50:46

+0

@prosseek:不會。自動釋放一個對象會把它放到最頂層的自動釋放池中。在'main'中,不存在其他自動釋放池,但是您創建的是其他自動釋放池;因此,您需要創建一個池(隱式)將數組自動釋放。否則,您會在控制檯日誌中看到一條日誌消息,並且數組(無自動釋放池釋放它)將被泄漏。 – 2011-02-28 04:53:37

+0

如果在註釋中沒有自動釋放對象的自動釋放對象,例如變量「month」,則該對象從不釋放,並導致內存泄漏。 – koo 2011-02-28 04:55:45