实例变量的分配?

时间:2009-09-09 17:30:47

标签: objective-c memory

有人能告诉我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;
}

初始& 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:我没有使用属性或合成,我还没有那么远。

欢呼 - 加里 -

4 个答案:

答案 0 :(得分:3)

您的代码有效,但可能没有理由将planetName初始化为空字符串。 Objective-C的一个很好的功能是你可以将消息发送到一个没有任何后果的nil对象。如果您的类已初始化且您从未调用-setPlanetName:,则planetName将为nil(实例变量始终初始化为nil),因此当您的-dealloc方法调用[planetName release]时,会发生。

通常,最佳做法是在设置NSString实例变量时使用-copy,在将大多数其他对象设置为实例变量时使用-retain。因此,您的-setPlanetName:方法看起来像这样:

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

答案 1 :(得分:1)

planetName是指针,与 int float 一样,不需要分配或初始化。

就像你可以为int或float赋值,你可以将planetName指向字符串的不同实例,或者它可以指向任何内容。

当你开始上课时,planetName将是nil(不指向任何东西)。如果将planetName指向字符串的实例,则必须保留该字符串,并在dealloc中 release

换句话说,这个:

planetName = [[NSString alloc] init];

是不必要的,毫无意义。

setPlanetName 方法中,您需要释放 planetName指向的现有字符串,将planetName分配给新字符串,然后保留新字符串。

您的 dealloc 方法是正确的。

答案 2 :(得分:1)

您的新代码仍然存在问题。

在您的主要功能中,您释放newPlanetName,但这有点不对劲。您的PlanetClasssetPlanetName:方法保留了它,但除非行星名称发生变化,否则PlanetClass永远不会再发布它。不应该由setPlanetName:的调用者来保持字符串,你的班级有责任妥善处理它。

您的旧dealloc方法是正确的。它应该释放行星的名字,因为你的PlanetClass不再需要它。你的主要方法不应该释放行星的名称,因为stringWithString:返回的字符串不属于你,你将它交给PlanetClass来处理。

因此,请保留旧的dealloc方法,并从主要功能中移除[newPlanetName release],您应该可以从那里开始。

作为一种快捷方式,您甚至可以拨打[newPlanet_01 setPlanetName:@"Jupiter"]并在主要功能中完全取消newPlanetName变量。

答案 3 :(得分:0)

您的代码看起来不错。 NSObject子类(包括NSString)需要由拥有它们的对象管理其内存。在这种情况下,该所有者为PlanetClass