了解临时对象的使用

时间:2013-06-13 13:40:52

标签: ios objective-c memory-management

也许这是一个愚蠢的问题,但我认为无论如何我都会问它,因为我仍然试图围绕内存管理。

这是:

1

ViewController *tViewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
self.viewController = tViewController;
[tViewController release];

比这更好:

2

self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease];

如何以及为何?

修改

好的,首先,我已经安全地发布了我拥有的任何东西。我可以看到这种情况发生了。

但是在第二种情况下,它是一个延期版本,所以如何判断它何时消失?这种autorelease这种东西让我很困惑。

这不是程序中唯一可能发生此类事件的实例。当我想要一个特定的物体时,我已经创造了活着,直到上帝知道什么时候,我该怎么办?我autorelease吗?但如果它在错误的时间消失了?那我该怎么办?

4 个答案:

答案 0 :(得分:3)

最终结果在两者中是相同的,但他们到达那里的方式是不同的。在这两种情况下,您都要创建一个稍后发布的临时引用。

第一个版本在发布时立即释放实例(确定性) - 虽然因为self.viewController可能是一个强引用,所以实例不会在发布调用时释放。

当取消分配当前自动释放池时,第二个版本在将来的某个时刻(非确定性)释放实例。再次 - 如果self.viewController持有对它的引用将不会被释放。

答案 1 :(得分:1)

两者都是一样的。唯一的区别是1有一个参考[​​tViewController]来设置实例,而在2中它是直接完成的。

答案 2 :(得分:0)

事情是,在第一种情况下,您手动释放viewController。它立即被摧毁。在第二种情况下,对象在事件循环结束时被销毁。 有时候,如果我在一个具有大量自动释放对象的函数中执行内存消耗 - 我会创建自动释放池,并且每次迭代都会耗尽它。

来自NSAutoreleasePool类参考:

Application Kit在事件循环的每个循环开始时在主线程上创建一个自动释放池,并在最后将其排出,从而释放处理事件时生成的任何自动释放的对象。 /强>

答案 3 :(得分:0)

我总是在书中说,第二种方式是更好的方式。但在过去,有些人不同意,尤其是在iOS上。有什么区别?

  1. 有什么不同吗?
  2. 两个变体都分配一个对象。两种变体都会照顾它。 (“Autorelease是一个版本。”)但是他们在不同的时间点做到了这一点:

    1. 变体:该对象在ARP结束时释放,至少在runloop结束时释放。
    2. 变式2:使用release即时释放对象。
    3. (两者:如果没有额外的参考。)

      1. 为什么我需要-autorelease?
      2. 在某些情况下,如果不违反MM规则,则无法release。最简单的情况是您想要返回已分配的对象。谁应该释放它?创建方法?这将返回可能已取消分配的内容。发送消息的方法?这会使alloc等+1方法与-1 release等方法失衡。没办法。

        示例:

        - (NSString*)fullName
        {
           NSString *fullName = [[NSString alloc] initWithFormat:@"%@, %@", self.lastName, self.firstName];
           return fullName; // Who balance +alloc?
        }
        

        通过自动释放对象,您的方法保持平衡并可以安全地返回对象。

        在其他情况下,它是摆脱依赖关系的便捷方式。想象一下这段代码:

        Person *person = …;
        NSString *name = person.name;
        [person release], person=nil; // Imagine that this will dealloc the instance.
        // name is invalid, because person released it.
        

        使用autorelease您没有遇到此问题。有几种解决方案:

        getter将retainautorelease发送给返回值。 ARP预防中还有一个参考来自dealloction的字符串:

        - (NSString*)name
        { return [[_name retain] autorelease]; }
        

        或者使用该方法的那个人做到了:

        NSString *name = [[person.name retain] autorelease];
        

        release问题的下一个问题是,使用returnbreakcontinue更加困难:

        while (…)
        {
            id object = [[Class alloc] …]
            if (…)
            {
               break;
            }
            [object release];
        }
        

        自动释放没有问题。

        下一篇:出于某些原因,使用便利分配器(如果存在)是个好主意。从那里返回的对象不允许显式释放,因此放弃引用的代码依赖于引用的设置方式。为什么不一直使用自动释放?

        1. autorelease的缺点是什么
        2. 对象删除可能会延迟,因此您可能会遇到内存占用问题。但我个人认为,@autorelease{}是比release更好的解决方案。