2009-10-01 102 views
1

這是上一個問題的後續問題,希望更清楚一點。我只是好奇下面提供的代碼是如何工作的,特別是變量myString被髮布。它看起來不像是從輸出?保留計數並複製二傳手?

CODE

// IMPLEMENT 
@implementation CelestialBody 
- (void)setName:(NSString *)newName{ 
    if(name != newName) { 
     [name release]; 
     name = [newName copy]; 
    } 
} 
- (void)dealloc{ 
    [name release]; 
    name = nil; 
    [super dealloc]; 
} 
@end 

// ------------------------------------------------------------------- ** 
// MAIN: 30th September 2009 
// ------------------------------------------------------------------- ** 

#import <Foundation/Foundation.h> 
#import "CelestialBody.h" 

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

    CelestialBody *newPlanet = [[CelestialBody alloc] init]; 
    NSString *myString = [[NSString alloc]initWithFormat:@"go home"]; 
    NSLog(@"RetainCount_1: %d",[myString retainCount]); 

    [newPlanet setName: myString]; 
    NSLog(@"RetainCount_2: Incremented by copy in setName");  

    // Clean up 
    NSLog(@"RetainCount_2: %d -Before Release",[myString retainCount]); 
    [newPlanet release]; 
    [myString release]; 
    [pool drain]; 
    NSLog(@"RetainCount_1: %d -After Release",[myString retainCount]); 
    return 0; 
} 
// ------------------------------------------------------------------- ** 

輸出

Running… 
2009-10-01 09:28:50.395 RetainCount_1: 1 
2009-10-01 09:28:50.399 RetainCount_2: Incremented by copy in setName 
2009-10-01 09:28:50.399 RetainCount_2: 2 -Before Release 
2009-10-01 09:28:50.400 RetainCount_1: 1 -After Release 
Debugger stopped. 

我目前重新讀Memeory管理指南試試,看看我已經錯過了。

千恩萬謝

編輯

只是增加了一個釋放的dealloc的,看起來這是我失蹤了。

- (void)dealloc{ 
    [name release]; 
    name = nil; 
    [super dealloc]; 
} 

加里

+2

不用擔心-retainCount。別叫它。不要打印它。不要考慮它。這沒有用。保持計數應被視爲增量;你增加和減少,但潛在價值不是你關心的。 – bbum 2009-10-01 15:52:43

回答

3

越來越發布mystring變量。

[myString release]; 

所有跡象都表明是肯定的。

它看起來不像是從輸出?因爲release消息尚未發生

NSLog(@"RetainCount_2: %d",[myString retainCount]); 
[myString release]; 

你的NSLog語句的輸出並不反映release消息。

另外,不要擔心保留數量。他們可能非常誤導。只要你遵循Cocoa的規則,不要創建任何所有權週期(A擁有B擁有C擁有A),你很少會遇到問題。

+0

對不起,我更新了代碼。 – fuzzygoat 2009-10-01 09:52:19

+3

+1。不要擔心保留數量。國際海事組織,蘋果應該刪除retainCount方法。初學者認爲他們可以依靠它而非僅僅學習規則,這太誘人了。 – Chuck 2009-10-01 12:20:06

+2

對於不擔心具體的保留數量不能達成一致。例如,如果您已將'myString'設置爲'NSMutableString',則'setName:'後的保留計數仍爲1。爲什麼?因爲'copy'在複製可變對象時會創建一個全新的對象。它保留了不變的對象,因爲複製其值不能改變的東西沒有意義。保留數是多少並不重要;只要遵守規則,你就會一直很好。 – Alex 2009-10-01 14:33:43

1

我猜[了newName副本]實際上並沒有複製的NSString,因爲的NSString是不可改變的?我從來沒有想過這件事,但對我來說很有意義。

在程序結束時,您將發佈newPlanet和myString。我的問題是,你是否在CelestialBody的-dealloc方法中釋放實例變量名稱?如果你不是,那麼我相信你在那裏泄漏了記憶。

  1. 創建的myString:所述的NSString的retainCount是1
  2. [newPlanet的setName:]:所述的NSString的retainCount是2
  3. [newPlanet釋放]:將的NSString的retainCount是2?我猜你不會在-dealloc中釋放它。
  4. [myString的發行]:NSString的的retainCount是1
+4

「我猜[newName copy]實際上並沒有複製NSString,因爲NSString是不可變的?」正確,但不要擔心,或者保留計數。保留計數可能會造成誤導,部分原因是由於這樣的優化。只要你遵循Cocoa的對象管理規則,你就不會有問題。 – 2009-10-01 08:49:02

2

這不是對您的問題本身的答案,而是對您所看到的內容的解釋:對retainCount的最後一次調用被髮送到未分配的對象,這是未定義的行爲。該對象發生還沒有被覆蓋,所以它仍然是一種「工作」,因爲方法調度仍然可以看到那裏的舊數據並且沒有意識到它是無效的。從調用retainCount起,您將永遠不會返回0,因爲這樣的對象不能存在。