Objective-C在声明对象时实际上做了什么?

时间:2011-06-10 18:58:13

标签: objective-c ios memory-management

我已经阅读了Apple的内存管理指南,我看不出这个案例的解释位置......

很多时候,特别是在编写类方法来返回类的实例时,我会像这样开始,因为这就是我看到它完成的方式,并且它有效。

[注意]这段代码来自内存 - 当我回到家时,我会更新它以显示一个真正有用的例子(我做了这个来说明它,但显然我不记得它构建一些东西这是有道理的......

[编辑]这是我的实际方法 - 当然每个人都应该打电话给我alloc

+ (id)player
{
    Player *player = nil;
    if ((player = [[[super alloc] initWithFile:@"rocket.png"] autorelease])) {
    [player setProjectileType:kProjectileBullet];
        [player setProjectileLevel:1];
        [player setInvincible:YES];
        [player setEmitter:[CCParticleSystemQuad particleWithFile:@"exhaust.plist"]];
        [[player emitter] setPosition:ccp(0.0, player.contentSize.height/2)];
        [player addChild:player.emitter];
    }
    return player;
}

所以我从回复中得到的是:   *声明实例只是获取一个指向内存位置的指针,并告诉Xcode该对象将是什么类。   *将指针设置为nil几乎只是将其设置为零 - 防止其中有垃圾(对吗?)   *由于我是自动释放实例,因此返回的对象也是自动释放的。

感谢您帮助我理解这一点!

3 个答案:

答案 0 :(得分:11)

  

有人可以解释编译器在看到这个时会做什么吗?

    DooDad* aDooDad = nil;

如果您真的对编译器的作用感兴趣,答案是:编译器将在堆栈上为局部变量aDooDad保留一些内存,这是一种指针类型(通常为64位或32位)大小取决于处理器)。然后将该指针初始化为包含nil(通常为0x00..00)。

这样的陈述:

         DooDad* aDooDad = [[DooDad alloc] init...];

利用指针变量aDooDad将地址存储在进一步分配的对象的内存中(这是alloc保留的内存地址)。

所以,最后,

    DooDad* aDooDad = nil;

不是声明一个对象,只是一个变量,其内容被解释为DooDad类型对象的地址。因此,这种声明就像你知道的任何其他声明一样,例如:将int初始化为0时,以便稍后可以在if语句中为其分配一些值。

如下的陈述:

 [aDooDad doSomething];

由Objective-C运行时系统解释,如:将消息doSomething发送到其地址存储在aDooDad中的对象。如果该地址为nil,则不会发送任何消息。另一方面,如果您取消引用一个零指针:*aDooDad,您将获得未定义的行为。

指针是相当低级的东西。我希望这会有所帮助。

答案 1 :(得分:4)

如果你熟悉C或C ++,变量可以用两种方式之一创建,静态地在调用堆栈上创建,或者在堆上动态创建。当前堆栈帧超出范围时,将回收在堆栈上创建的可变内存,因此您无需担心创建或销毁它。在Objective-C中,对象始终动态创建。基元(如int,float,指针等)可以静态或动态创建。例如:

- (id)something {

    NSObject myObject; // Illegal static object allocation
    NSObject* myObject; // Legal primitive (pointer) static allocation
    int myInt; // Legal primitive static allocation
    int* myIntPtr; // Legal primitive (pointer) static allocation
}

所以当你说DooDad* dodad = nil;时,你正在堆栈上创建一个原语(指向DooDad的指针)。作为堆栈变量,您不会分配或取消分配它,就像您不必担心在以下方法中分配或释放任何内存:

- (id)allStackVariables {
    int myInt = 0;
    float myFloat = 0.0f;
    float* myFloatPtr = NULL;
    NSObject* myObject = nil;
}

将其设置为nil只需将变量的内容设置为编译器定义为nil的内容,如十六进制中的0x000000。说DooDad* dooDad = nil;在概念上与说int myInt = 0;

之类的内容相同

答案 2 :(得分:2)

声明simple会为您提供一个稍后可以使用的指针。没有分配内存。

不确定您发布的方法的意图,但在许多级别上似乎都是错误的。总是会返回零。除非它是初始化方法,否则不应该调用[self init]。如果它是初始化方法,它应该返回self并命名为“init ...”