2012-04-02 96 views
2

這是我的代碼:關於自動釋放/釋放和[池釋放]

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
NSString *string = [[NSString alloc] initWithFormat:@"s"]; 

[string autorelease]; 
NSLog(@"retainCount of string is %d", [string retainCount]); 

[pool release]; 
NSLog(@"retainCount of string is %d", [string retainCount]); 

當我試着去了解自動釋放和釋放,我很困惑。 如果使用[string autorelease],發送釋放消息到pool後,字符串的retainCount仍然是1.但是用[string release]來代替[string autorelease],最後string的retainCount將是0.我對autorelease的瞭解是「通過發送一個autorelease消息將對象添加到當前的自動釋放池中供以後發佈」。爲什麼我向它發送一個autorelease消息並釋放池,我仍然可以訪問該對象。

+1

retainCount永遠不會返回零。發送解除分配的對象會產生未定義的行爲。 – bbum 2012-04-02 15:21:23

回答

3

這是事情:retainCount是一個實現細節。你永遠不能依靠它是任何具體的價值。你真正需要考慮的是你是否擁有一個物體。

分配字符串後,您擁有它。當你自動釋放字符串時,你不再擁有它,當你釋放/釋放自動釋放池時它可能會消失。如果沒有其他人擁有它,當您釋放自動釋放池時,消失。總之,在釋放autorelease池之後,你無法合法地發送字符串消息。

在當前的實現中,字符串的保留計數爲1創建。autorelease不會更改保留計數。當池被釋放時,release被髮送到它的所有對象,包括你的字符串。在發佈的代碼看起來是這樣的:

if (retainCount == 1) 
{ 
    [self dealloc]; 
} 
else 
{ 
    retainCount--; 
} 

所以你可以看到,保留計數將永遠不會降到零。您的最終NSLog工作,因爲字符串使用的內存尚未回收。

+0

謝謝你!這有助於我理解Objective-C的內存管理。 – tzzzoz 2012-04-02 08:50:21

-1

您必須使用[pool drain]而不是發佈消息來釋放池中的所有自動釋放對象。此消息將爲您撥打[游泳池發佈]

+0

'drain'與引用計數代碼中的'release'同義。 – JeremyP 2012-04-02 08:28:53

+0

我試過這種方法。但字符串的retainCount仍然在控制檯中打印。 – tzzzoz 2012-04-02 08:29:50

+0

從'NSAutoreleasePool'引用:「當釋放自動釋放池被釋放時,它向所有自動釋放對象發送釋放消息」 – trojanfoe 2012-04-02 08:30:29