-dealloc 方法在拥有数组 dealloc'd 时不被调用...应该吗?

Posted

技术标签:

【中文标题】-dealloc 方法在拥有数组 dealloc\'d 时不被调用...应该吗?【英文标题】:-dealloc method not called when owning array dealloc'd... should it?-dealloc 方法在拥有数组 dealloc'd 时不被调用...应该吗? 【发布时间】:2011-01-25 01:40:39 【问题描述】:

这是 Foundation 应用程序中的两段 Objective-C 代码。这段代码在一个函数中:

    [arrayOfObjects addObject:[[TheShape alloc] init]];
    NSLog(@"%@", arrayOfObjects); // log verifies "<TheShape..." is in the array
    [arrayOfObjects release];

在我的 TheShape 类中,我有这个 dealloc 覆盖方法:

    - (void)dealloc 
        NSLog(@"TheShape dealloc called.");
        [super dealloc];
    

虽然我的程序可以正常工作,但它并没有按我预期的方式工作。当发送[arrayOfObjects release] 消息时,我希望看到“TheShape dealloc...”字符串出现在日志中。没有。

Q1:为什么不呢?

所以我挖掘了一下并简化了一些事情。如果我这样做更简单:

    TheShape *aShape = [[TheShape alloc] init];
    [aShape release];

调试消息仍然没有出现在日志中。

Q2:为什么不呢?

但如果我这样做:

    TheShape *aShape = [TheShape new];
    [aShape release];

调试消息确实出现在日志中。如果我将第一个示例中的 alloc/init 也更改为 new,调试消息也会出现在日志中。

Q3:为什么?

显然,我在 alloc/init/release 周期(Q 的 1 和 2)以及假定的 newalloc/init(Q3)的等效性中遗漏了一些概念性的东西。任何人都可以向我指出一个教程,该教程可以像我一样对难以思考的事物进行更多解释吗?

谢谢,

比尔

【问题讨论】:

TheShape *aShape = [[TheShape alloc] init];TheShape *aShape = [TheShape new];应该没有区别。 【参考方案1】:

你有没有在你的课堂上覆盖+new?它应该与+alloc/-init 做完全相同的事情。

无论如何,你的第一行

[arrayOfObjects addObject:[[TheShape alloc] init]];

正在泄漏您的 TheShape 实例。你应该把它转成

[arrayOfObjects addObject:[[[TheShape alloc] init] autorelease]];

【讨论】:

我没有覆盖 +new 类,但如果我有的话,我可以看出哪里会出现问题。我希望 new 的行为与 alloc/init 完全一样,但这并不是出于某种奇怪的原因。我仍然对此感到疑惑。 不过,制作 TheShape 自动释放就可以了。第一次发生了什么?是的,我分配/初始化,所以拥有该对象,但 arrayOfObjects 最终不必为我跟踪它吗?这是我清楚地认为应该发生一件事而 Objective-C 内存管理的基本规则似乎不一致的情况之一。澄清将不胜感激。 数组不会“接管”您对对象的所有权。它正在增加自己的所有权。一个对象可以由多个其他对象拥有。在这种情况下,数组拥有它,但您的本地方法也是如此。您需要在阵列拾取它后放弃对它的所有权。 啊,zneak(下)为我回答了这个问题。 (我猜,提前阅读是值得的。)【参考方案2】:

没有理由调用 dealloc 方法:您的对象仍然具有非零引用计数。

每当您创建一个对象时,它的引用计数为 1。一旦该计数达到 0,它就会被释放。内存管理有一些特定的规则可以帮助我们保持清醒。这些规则谈到“对象所有权”。

基本上,如果您满足以下条件之一,您将成为对象的所有者:

你在对象上调用retain; 您通过在另一个对象上调用copymutableCopy 来获取一个对象; 您在对象上调用alloc 方法。

当您拥有一个对象时,您有责任在不再需要它时释放它。只有在没有人需要时才会删除它。

在你的 sn-p 中,创建你传递给你的数组的对象。您的数组开始使用它,因此它会在其上调用retain(因此它在被持有时保持活动状态)。但是,一旦您 release 数组,您的对象仍然需要由 释放,因为您调用了 alloc 方法。


编辑简单的 sn-p:

TheShape *aShape = [[TheShape alloc] init];
[aShape release];

应该显示消息,但是。 :/

我认为这没有发生的原因有两个:

您使用allocinitrelease 方法做了一些奇怪的事情(在这种情况下,请发布您的代码); 你在垃圾收集环境中运行,dealloc 将永远不会被调用(在这种情况下你应该使用finalize)。虽然我不明白为什么 +new 然后 release 会给出预期的结果。

【讨论】:

-init 并不意味着所有权。另一方面,名称中包含allocnew 的方法可以。 虽然我理解 Bavarious 所说的(CAN=ownership),但我不确定他在您的原始帖子中指的是什么……哦,没关系。我刚刚点击了修订链接。知道了。谢谢,伙计们!

以上是关于-dealloc 方法在拥有数组 dealloc'd 时不被调用...应该吗?的主要内容,如果未能解决你的问题,请参考以下文章

数组拓展方法

让js中数据类型的所有方法都通用起来

使用数组向量的正确方法

我如何在Javascript中拥有可变长度数组的前3个元素[重复]

是啥让一个指向页表条目的指针数组比拥有一个页表条目数组更好?

如何在 mysql Sequelize 实例中拥有数组的数据类型?