【问题标题】:What does Objective-C actually do when you declare an object?当你声明一个对象时,Objective-C 实际上做了什么?
【发布时间】:2011-09-12 17:51:26
【问题描述】:

我已经阅读了 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 几乎只是将其设置为零 - 防止它在其中包含垃圾(对吗?) * 因为我是自动释放实例,所以返回的对象也是自动释放的。

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

【问题讨论】:

  • 你在哪里见过上面的“完成”?您在此处列出的代码没有意义,我不希望它起作用。
  • @Rob - 见我上面的编辑;今晚我将使用实际代码进行编辑。感谢您的耐心。

标签: objective-c ios memory-management


【解决方案1】:

有人能解释一下编译器在看到这个时会做什么吗?

    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,则不会发送任何消息。另一方面,如果您取消引用 nil 指针:*aDooDad,您将获得未定义的行为。

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

【讨论】:

    【解决方案2】:

    如果您熟悉 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; 之类的话

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 抱歉,我是凭记忆输入的。除了指针声明部分外,我不确定确切的代码。我知道我没有打电话给alloc,,而只是打电话给init。它是cocos2d 项目的一部分,我的实际类是CCSprite, 的子类,init 方法是initWithFile:
      • @Steve:在 nil 值上调用 init 是无操作的,当然不会做任何有用的事情。
      猜你喜欢
      • 2015-08-15
      • 2011-11-27
      • 2015-01-25
      • 1970-01-01
      • 2013-06-02
      • 2020-11-21
      • 2015-02-26
      • 2017-06-29
      • 2013-06-13
      相关资源
      最近更新 更多