【问题标题】:Allocation of instance variables?分配实例变量?
【发布时间】:2009-09-09 17:30:47
【问题描述】:

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

init 和 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:我没有使用属性或合成,我还没有走到那一步。

干杯-加里-

【问题讨论】:

  • NSString *newPlanetName = [NSString alloc] init] 只是内存泄漏,因为您立即将不同的 NSString 分配给变量并且永远不会释放旧值。

标签: objective-c memory


【解决方案1】:

您的代码是有效的,但可能没有理由将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;
}

【讨论】:

  • 并非所有对象都初始化为零,只有实例变量。在堆栈上创建的对象指针保持未初始化。
  • 您应该考虑将planetName 设为@property(nonatomic,copy)。
【解决方案2】:

您的新代码仍有问题。

在你的 main 函数中,你释放了 newPlanetName 但这有点错误。你的PlanetClass 使用它的setPlanetName: 方法保留了它,但是你的PlanetClass 永远不会再次释放它,除非行星的名称发生变化。不应该由setPlanetName: 的调用者来控制字符串,你的类有责任适当地处理它。

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

所以,保留你旧的dealloc 方法,并从主函数中删除[newPlanetName release],你应该会没事的。

作为一种快捷方式,您甚至可以调用 [newPlanet_01 setPlanetName:@"Jupiter"] 并在主函数中完全取消 newPlanetName 变量。

【讨论】:

  • 我明白为什么我需要在 dealloc 方法中添加一个 [planetName release]。这样当类被释放时,当前复制的 newPlanet 版本就会被释放。当我分配内存时,我对 newPlanetName 有点困惑,然后分配 @"Jupiter" 我的印象是需要释放 newPlanet(上面的代码已修改)
  • 这是一个常见的误解。您在主函数中的newPlanetName 变量是一个指向对象的指针。当您使用[[NSString alloc] init] 时,所做的只是分配和初始化一个空字符串,您的newPlanetName 变量指向该字符串。当你给它分配一个像@"Jupiter" 这样的值时,你改变了newPlanetName 指向的位置,实际上它指向的原始对象(空字符串)现在不再可访问。
  • 这就是我的想法... () newPlanetName 是一个指向字符串对象的指针,最初它指向 nil。 () newPlanetName = @"Jupiter" 将该指针设置为指向字符串文字,我认为您不需要释放字符串文字,这很好。 但是
  • IF newPlanetName = someOtherStringObject 然后它指向一个实际的对象,然后我应该释放 newPlanetName,还是 someOtherStringObject 的所有者的工作,这可能是我,所以我需要做[someOtherStringObject 版本]?
  • 你肯定在朝着正确的方向前进。您不需要释放文字字符串是对的,但是关于释放其他对象,这完全取决于您如何获取它们。如果方法包含单词“new”、“alloc”或“copy”,那么您有责任释放它。还有一些其他情况需要显式释放,但您应该查看 Cocoa 内存管理文档以获取更多信息。
【解决方案3】:

planetName 是一个 pointer,与 intfloat 一样,不需要分配或初始化。

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

当你初始化你的类时,planetName 将为 nil(不指向任何东西)。如果你将planetName 指向一个字符串的实例,你必须retain 该字符串,并在dealloc 中release

换句话说,这个:

planetName = [[NSString alloc] init];

是不必要且毫无意义的。

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

你的 dealloc 方法是正确的。

【讨论】:

    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 2014-06-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-28
      • 1970-01-01
      • 1970-01-01
      • 2021-06-18
      • 2011-09-07
      • 2020-02-18
      相关资源
      最近更新 更多