2009-10-01 100 views
1

这是上一个问题的后续问题,希望更清楚一点。我只是好奇下面提供的代码是如何工作的,特别是变量myString被发布。它看起来不像是从输出?保留计数并复制二传手?

CODE

// IMPLEMENT 
@implementation CelestialBody 
- (void)setName:(NSString *)newName{ 
    if(name != newName) { 
     [name release]; 
     name = [newName copy]; 
    } 
} 
- (void)dealloc{ 
    [name release]; 
    name = nil; 
    [super dealloc]; 
} 
@end 

// ------------------------------------------------------------------- ** 
// MAIN: 30th September 2009 
// ------------------------------------------------------------------- ** 

#import <Foundation/Foundation.h> 
#import "CelestialBody.h" 

int main (int argc, const char * argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    CelestialBody *newPlanet = [[CelestialBody alloc] init]; 
    NSString *myString = [[NSString alloc]initWithFormat:@"go home"]; 
    NSLog(@"RetainCount_1: %d",[myString retainCount]); 

    [newPlanet setName: myString]; 
    NSLog(@"RetainCount_2: Incremented by copy in setName");  

    // Clean up 
    NSLog(@"RetainCount_2: %d -Before Release",[myString retainCount]); 
    [newPlanet release]; 
    [myString release]; 
    [pool drain]; 
    NSLog(@"RetainCount_1: %d -After Release",[myString retainCount]); 
    return 0; 
} 
// ------------------------------------------------------------------- ** 

输出

Running… 
2009-10-01 09:28:50.395 RetainCount_1: 1 
2009-10-01 09:28:50.399 RetainCount_2: Incremented by copy in setName 
2009-10-01 09:28:50.399 RetainCount_2: 2 -Before Release 
2009-10-01 09:28:50.400 RetainCount_1: 1 -After Release 
Debugger stopped. 

我目前重新读Memeory管理指南试试,看看我已经错过了。

千恩万谢

编辑

只是增加了一个释放的dealloc的,看起来这是我失踪了。

- (void)dealloc{ 
    [name release]; 
    name = nil; 
    [super dealloc]; 
} 

加里

+2

不用担心-retainCount。别叫它。不要打印它。不要考虑它。这没有用。保持计数应被视为增量;你增加和减少,但潜在价值不是你关心的。 – bbum 2009-10-01 15:52:43

回答

3

越来越发布mystring变量。

[myString release]; 

所有迹象都表明是肯定的。

它看起来不像是从输出?因为release消息尚未发生

NSLog(@"RetainCount_2: %d",[myString retainCount]); 
[myString release]; 

你的NSLog语句的输出并不反映release消息。

另外,不要担心保留数量。他们可能非常误导。只要你遵循Cocoa的规则,不要创建任何所有权周期(A拥有B拥有C拥有A),你很少会遇到问题。

+0

对不起,我更新了代码。 – fuzzygoat 2009-10-01 09:52:19

+3

+1。不要担心保留数量。国际海事组织,苹果应该删除retainCount方法。初学者认为他们可以依靠它而非仅仅学习规则,这太诱人了。 – Chuck 2009-10-01 12:20:06

+2

对于不担心具体的保留数量不能达成一致。例如,如果您已将'myString'设置为'NSMutableString',则'setName:'后的保留计数仍为1。为什么?因为'copy'在复制可变对象时会创建一个全新的对象。它保留了不变的对象,因为复制其值不能改变的东西没有意义。保留数是多少并不重要;只要遵守规则,你就会一直很好。 – Alex 2009-10-01 14:33:43

1

我猜[了newName副本]实际上并没有复制的NSString,因为的NSString是不可改变的?我从来没有想过这件事,但对我来说很有意义。

在程序结束时,您将发布newPlanet和myString。我的问题是,你是否在CelestialBody的-dealloc方法中释放实例变量名称?如果你不是,那么我相信你在那里泄漏了记忆。

  1. 创建的myString:所述的NSString的retainCount是1
  2. [newPlanet的setName:]:所述的NSString的retainCount是2
  3. [newPlanet释放]:将的NSString的retainCount是2?我猜你不会在-dealloc中释放它。
  4. [myString的发行]:NSString的的retainCount是1
+4

“我猜[newName copy]实际上并没有复制NSString,因为NSString是不可变的?”正确,但不要担心,或者保留计数。保留计数可能会造成误导,部分原因是由于这样的优化。只要你遵循Cocoa的对象管理规则,你就不会有问题。 – 2009-10-01 08:49:02

2

这不是对您的问题本身的答案,而是对您所看到的内容的解释:对retainCount的最后一次调用被发送到未分配的对象,这是未定义的行为。该对象发生还没有被覆盖,所以它仍然是一种“工作”,因为方法调度仍然可以看到那里的旧数据并且没有意识到它是无效的。从调用retainCount起,您将永远不会返回0,因为这样的对象不能存在。