Objective c 实例变量的分配?

Objective c 实例变量的分配?,objective-c,memory,Objective C,Memory,有人能告诉我NSString实例变量“planetName”是否需要由我分配/释放(如下例所示),还是在创建/分配类实例时完成 我的理解是int和float不需要,但不确定NSString和NSArray @interface PlanetClass : NSObject { NSString *planetName; } - (NSString *)planetName; - (void)setPlanetName:(NSString *)value; @end 像这样 -

有人能告诉我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];
}
- (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];
}
- (void)setPlanetName:(NSString *)newPlanetName {
        if (planetName != newPlanetName) {
               [planetName release];
               planetName = [newPlanetName copy];
        }
}
**--------------------------------------** 编辑:编辑:这是另一个版本 **--------------------------------------**

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;
}
init&dealloc方法将如下所示

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

- (void) dealloc {
        [planetName release];
        [super 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];
}
- (void)setPlanetName:(NSString *)newPlanetName {
        if (planetName != newPlanetName) {
               [planetName release];
               planetName = [newPlanetName copy];
        }
}
setPlanetName方法将如下所示

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

- (void) dealloc {
        [planetName release];
        [super 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];
}
- (void)setPlanetName:(NSString *)newPlanetName {
        if (planetName != newPlanetName) {
               [planetName release];
               planetName = [newPlanetName copy];
        }
}
附言:我没有使用属性或合成,我还没有做到这一点


干杯-gary-

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

通常,最佳做法是在设置NSString实例变量时使用
-copy
,在将大多数其他对象设置为实例变量时使用
-retain
。因此,您的
-setPlanetName:
方法如下所示:

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

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

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

就像可以为int或float赋值一样,可以将planetName指向字符串的不同实例,也可以不指向任何对象

初始化类时,planetName将为nil(不指向任何对象)。如果将planetName指向字符串的实例,则必须保留该字符串,并在dealloc中释放

换言之,这:

planetName = [[NSString alloc] init];
没有必要,也没有意义

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


您的dealloc方法是正确的。

您的新代码仍然存在问题

在main函数中,您发布了
newPlanetName
,但这有点错误。你的
PlanetClass
用它的
setPlanetName:
方法保留了它,但是你的
PlanetClass
永远不会释放它,除非行星的名称改变。
setPlanetName:
的调用者不应掌握字符串,而应由您的类负责适当地处理它

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

因此,保留旧的
dealloc
方法,并从主函数中删除
[newPlanetName release]
,这样您就不会有问题了


作为一种快捷方式,您甚至可以调用
[newPlanet\u 01 setPlanetName:@“Jupiter”]
并在主函数中完全删除
newPlanetName
变量。

That
NSString*newPlanetName=[NSString alloc]init]
只是一个内存泄漏,因为您会立即为变量分配不同的NSString,而不会释放旧值。并非所有对象都初始化为nil,只有实例变量。在堆栈上创建的对象指针仍处于未初始化状态。您应该使用concider将planetName设置为@property(非原子,复制)。我可以理解为什么需要将[planetName release]添加到dealloc方法中。因此,当类被释放时,newPlanet的当前复制版本将被释放。我对newPlanetName有点困惑,因为我分配内存,然后分配“Jupiter”,我的印象是newPlanet需要被释放(上面的代码被修改),这是一个常见的误解。主函数中的
newPlanetName
变量是指向对象的指针。使用
[[NSString alloc]init]
时,只需分配并初始化一个空字符串,
newPlanetName
变量指向该空字符串。当你给它赋值时,比如
@“Jupiter”
,你改变了
newPlanetName
指向的位置,事实上,它指向的原始对象(空字符串)现在不再是可访问的。这就是我想的。。。()newPlanetName是指向字符串对象的指针,最初它指向nil。()newPlanetName=@“Jupiter”将指针设置为指向字符串文本,我认为您不需要释放字符串文本,所以这很好。但是如果newPlanetName=someOtherStringObject,那么它指向的是一个实际的对象,那么我应该发布newPlanetName吗,或者这是某个其他StringObject的所有者的工作,可能是我,所以我需要执行[someOtherStringObject发布]?你的方向肯定是正确的。关于不需要释放文本字符串,您是对的,但是关于释放其他对象,这完全是关于如何获得它们。如果该方法包含单词“new”、“alloc”或“copy”,则您负责发布该方法。还有一些其他实例需要显式释放,但您应该查看Cocoa内存管理文档以了解更多信息。