2009-09-09 194 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方法是否正确。