2009-09-09 106 views
3

任何人都可以告訴我,如果NSString實例變量「planetName」需要由我分配/釋放(如下例所示)還是在創建/分配類實例時完成的?分配實例變量?

我的理解是,int和float不需要是,但不知道的NSString & NSArray的...

@interface PlanetClass : NSObject { 
     NSString *planetName; 
} 
- (NSString *)planetName; 
- (void)setPlanetName:(NSString *)value; 
@end 

就像這個...

- (id) init { 
     [super init]; 
     planetName = [[NSString alloc] init]; 
return self; 
} 

- (void) dealloc { 
     [planetName release]; 
     [super dealloc]; 
} 

** - --------------------------------- ** 編輯:編輯:這是另一個版本 ** --- ------------------------------- **

int main(int argc, const char *argv[]) { 

     // ** Allocated here 
     PlanetClass *newPlanet_01 = [[PlanetClass alloc] init]; 
     NSString *newPlanetName = [NSString alloc] init]; 

     // ** Set the instance variable pointer here 
     newPlanetName = @"Jupiter"; 
     [newPlanet_01 setPlanetName:newPlanetName]; 

     // ** Released here 
     [newPlanet_01 release]; 
     return 0; 
} 
0然後種

初始化& dealloc的方法會是這樣......

- (id) init { 
     [super init]; 
     return self; 
} 

- (void) dealloc { 
     // Always release the current copy of planetName 
     // pointed to by the class instance. 
     [planetName release] 
     [super dealloc]; 
} 

的setPlanetName方法是這樣的......

- (void)setPlanetName:(NSString *)newPlanetName { 
     if (planetName != newPlanetName) { 
       [planetName release]; 
       planetName = [newPlanetName copy]; 
     } 
} 

PS:我沒有使用性質或合成,我還沒有得到那麼多。

歡呼-gary-

+0

'NSString * newPlanetName = [NSString alloc] init]'只是一個內存泄漏,因爲您立即將一個不同的NSString賦值給該變量,並且永遠不會釋放舊值。 – Chuck 2009-09-09 20:57:21

回答

1

您的新代碼仍然存在問題。

在您的主要功能中,您發佈newPlanetName但這有點不對。您的PlanetClass保留了它的setPlanetName:方法,但您的PlanetClass不會再次釋放它,除非地球名稱改變。它不應該由setPlanetName:的調用者繼續保持字符串,這是您的類負責適當地處理它。

您的舊dealloc方法是正確的。它應該釋放星球的名字,因爲你的PlanetClass不再需要它。你的主要方法不應該釋放星球的名字,因爲由stringWithString:返回的字符串不屬於你,並且你給它PlanetClass照顧。

因此,請保留舊的dealloc方法,並從主函數中刪除[newPlanetName release],您應該從那裏繼續。

作爲一種快捷方式,您甚至可以撥打[newPlanet_01 setPlanetName:@"Jupiter"]並在主功能中完全取消newPlanetName變量。

+0

我可以看到爲什麼我需要添加一個[planetName發佈]到dealloc方法。所以當類被釋放時,newPlanet的當前複製版本被釋放。 我對newPlanetName有點困惑,因爲我正在分配內存,然後分配@「Jupiter」我的印象是需要發佈newPlanet(上面修改的代碼) – fuzzygoat 2009-09-10 11:27:12

+0

這是一個常見的誤解。主函數中的'newPlanetName'變量是指向對象*的*指針。當你使用'[[NSString alloc] init]'時,所有的工作就是分配和初始化一個空字符串,你的'newPlanetName'變量指向這個空字符串。當你給它賦值像「@」Jupiter「'時,你改變'newPlanetName'指向的位置,實際上它指向的原始對象(空字符串)現在不再可用了。 – dreamlax 2009-09-10 11:39:49

+0

這就是我在想...(*)newPlanetName是一個指向字符串對象的指針,最初它指向nil。 (*)newPlanetName = @「Jupiter」將該指針設置爲指向字符串文字,我不認爲你需要釋放字符串文字,所以這很好。 **但是** – fuzzygoat 2009-09-10 11:49:06

3

你的代碼是有效的,但可能沒有理由來初始化planetName爲空字符串。 Objective-C的一個很好的特性就是你可以發送消息給一個沒有結果的零對象。如果你的類被初始化並且你永遠不會調用-setPlanetName:,planetName將是零(實例變量總是被初始化爲nil),所以當你的-dealloc方法調用[planetName release]時,什麼都不會發生。

通常,最佳做法是在設置NSString實例變量時使用-copy,而在將大多數其他對象設置爲實例變量時使用-retain。因此,您的-setPlanetName:方法看起來像這樣:

- (void)setPlanetName:(NSString *)newPlanetName { 
    NSString *tempPlanetName = [newPlanetName copy]; 
    [planetName release]; 
    planetName = tempPlanetName; 
} 
+0

並非所有的對象都被初始化爲零,只有實例變量。在堆棧上創建的對象指針保持未初始化狀態。 – dreamlax 2009-09-10 07:32:01

+0

你應該concder使planetName成爲@property(非原子,複製)。 – PeyloW 2009-09-14 19:28:06

0

您的代碼看起來不錯。 NSObject子類(包括NSString)需要由擁有它們的對象來處理它們的內存。在這種情況下,該所有者爲PlanetClass

1

planetName是指針其中,像一個INT浮子,不需要分配或初始化。

就像您可以將值賦給int或float一樣,您可以將planetName指向字符串的不同實例,也可以不指向任何東西。

當你初始化你的類時,planetName將是零(不指向任何東西)。如果將planetName指向一個字符串的實例,則必須保留該字符串,並且在release中釋放

換句話說,這樣的:

planetName = [[NSString alloc] init]; 

是不必要的,並且毫無意義的。

在你setPlanetName方法,你將需要發佈現有的字符串planetName指向,分配planetName新的字符串,然後保留新的字符串。

您的dealloc方法是否正確。