【问题标题】:alloc and init what do they actually doalloc 和 init 他们实际上做了什么
【发布时间】:2010-10-03 07:37:24
【问题描述】:

谁能向我解释一下 init 和 alloc 在 Obj-C 中的作用。我正在阅读这本 obj-c 书,它提供了一个创建对象的示例,但并没有真正详细介绍它的作用。 alloc 返回什么? init 返回什么?

Animal * k = [Animal alloc];
k = [k init];

【问题讨论】:

    标签: objective-c


    【解决方案1】:
    • alloc 分配一块内存来保存对象,并返回指针。

      MyClass* myObj = [MyClass alloc];
      

      myObj 还不能使用,因为它的内部状态没有正确设置。所以,不要写这样的代码。

    • init 设置对象的初始条件并返回。请注意,[a init] 返回的内容可能与a 不同。这解释了 Yannick 编写的代码:

      -init{
           self=[super init]; // 1.
           if(self){          // 2.
               ....
           }
           return self;       // 3.
      }
      
      1. 首先,您需要调用超类的init,设置超类的实例变量等。这可能会返回不等于原始self 的内容,因此您需要将返回的内容分配给self
      2. 如果self 不为nil,则表示超类控制的部分已正确初始化。现在您执行初始化。所有实例变量都设置为nil(如果它是对象)和0(如果它是整数)。您需要执行其他初始设置。
      3. 返回设置self。返回的self 可能与分配的不同!因此,您需要将init 的结果分配给您的变量。

    这建议了一个重要的教训:永远不要将呼叫拆分为 allocinit。不要写:

     MyClass* myObj = [MyClass alloc];
     [myObj init];
    

    因为[myObj init] 可能会返回其他内容。不要试图通过写作来解决这个问题:

     MyClass* myObj = [MyClass alloc];
     myObj=[myObj init];
    

    因为你最终会忘记在第二行写 myObj= 部分。

    总是写:

     MyClass* myObj = [[MyClass alloc] init];
    

    我也不推荐写:

     MyClass* myObj = [MyClass new];
    

    因为它没有正确调用初始化方法:有些类不接受普通的init。比如NSView需要initWithFrame:,不能用new调用。所以,也不要使用new

    【讨论】:

    • 很好的解释!谢谢
    • 话虽如此,如果您不需要自定义-init,您可以直接调用+new。如果您查看+(id)new 的实现,它实际上是return [[self alloc]init];
    • 我有一个问题。变量 myObj 是指向内存位置的指针吗?你的观点“首先,你需要调用超类的init,设置超类的实例变量等。这可能会返回不等于原始自我的东西”,所以你的意思是在超类中再次分配一个新对象,因为指向内存位置变化的指针?
    • 一般init是初始化类成员的方法,为什么指针变化很奇怪!
    • @GilSand 我知道的老问题,但对于新手来说:使用alloc initnew 是非常好的做法。习惯性地使用alloc init 永远不会遇到错误,但习惯使用new 时可能会遇到错误。
    【解决方案2】:

    最简单的形式:

    • alloc:分配的缩写,保留一个内存位置并返回指向该内存位置的指针。然后将该指针存储在 k 变量中。

    • init:初始化的缩写,设置对象并返回对象。 init 方法取决于对象,但通常涉及将 init 消息发送到超类。如果(超类的)该 init 方法返回一个对象(不是 nil),则可能会根据该类的任务设置一些 ivars。

    --

    一个初始化实现的例子,Schedule 类用一个空数组初始化它的通道 ivar。基本上,您给 Schedule 对象一个自我整理的机会,这样它就可以在创建后开始接收消息。您可以从 init 方法中删除频道初始化,但是您必须检查频道 ivar 在 Schedule 类的每个方法中是否为 nil,如果确实为 nil,则对其进行初始化。

    - (Schedule*)init {
      self = [super init];
    
      if (self) {
        channels = [[NSMutableArray alloc] initWithCapacity:0];
      }
    
      return self;
    }
    

    【讨论】:

    • 设置对象是什么意思?他们返回什么?
    • 我已经稍微扩展了我的答案。
    【解决方案3】:

    alloc 和 init 是继承自 NSObject 的两个方法 您可以提供自己的方法或从 NSObject 调用方法

    alloc 分配内存来创建你的类的一个新实例(@interface) init 初始化该实例的内容,默认情况下 init 将所有成员值设置为 0/nil 但是您可以创建自己的 init 方法来自定义所做的事情。

    Animal * k = [[Animal alloc] init]; // creates a new Animal object
    

    你也可以写

    Animal * k = [Animal new]; // which would be a bit more similar to other languages
    

    【讨论】:

      【解决方案4】:

      NSObject 根类提供了一个类方法,allocalloc:保留一个内存位置并返回指向该内存位置的指针。

      alloc 方法还有另一项重要任务,即通过将分配给对象属性的内存设置为零来清除它们。

      这避免了内存包含之前存储的垃圾的常见问题,但是

      不足以完全初始化一个对象。

      您需要结合对 alloc 的调用和对 init 的调用,另一个 NSObject 方法:

      • (id)初始化; init 方法被一个类用来确保它的属性在创建时具有合适的初始值。 分配和初始化对象的正确方法是将 alloc 调用嵌套在对 init 的调用中,如下所示:

        ClassName *objectName = [ClassName alloc] init];

      来自:苹果文档

      【讨论】:

        【解决方案5】:

        Alloc 会为对象分配内存,但 Init 将对象放入内存并设置默认值。

        【讨论】:

        • 请解释你的答案。
        猜你喜欢
        • 2014-02-05
        • 2013-06-02
        • 2020-11-21
        • 2015-02-26
        • 2017-06-29
        • 2013-06-13
        • 2021-10-25
        • 2011-08-12
        • 1970-01-01
        相关资源
        最近更新 更多