1

我想知道您能否让我知道以下两种情况,它们几乎相似,但对象又小又大。

场景一:

在以下代码中:

NSString *iAmAstring;
for(int i = 0; i < 100000;i++)
{
     NSLog(@"INT VALUE: %d", i);
     iAmAstring = [NSString stringWithFormat:@"%d", i];
     NSLog(@"STRING VALUE: %@", iAmAstring);
}

有人告诉我,因为我打开了 ARC,所以对于我分配和初始化字符串指针的每个循环运行,执行上述大规模循环并在其中没有任何影响。因为有人告诉我它太小了,没关系,ARC可以处理它。但不要用更大的物体来做。我最初来自 C# 背景,我习惯于在循环结束时将我的字符串设置为 null,但是在这里你不能在循环结束时释放它,因为 ARC 会抱怨并且我被告知如果我将它设置为nil在循环结束时,我将为 ARC 创建更多工作,但我并没有真正做对,而是在创建僵尸代码。有人可以澄清他们会对他们正在分配的对象做什么,在循环结束时在 ARC 打开的情况下在一个内存大小很小的大型循环(最好是我使用的字符串)中初始化吗?

场景二:

与上面相同,但假设现在上面使用的 NSSTRING 现在是另一个尺寸很大的对象。在这里,我显然会在循环之前分配和初始化它,然后通过设置它在循环中使用它,但是我将如何在循环结束时再次对它做一些事情以释放它,所以再次打开 ARC?

提前致谢。

4

2 回答 2

4

在 ARC 下,您可以使用@autoreleasepool {}块定义自动释放池。这些块创建新的自动释放对象池,并在块范围结束时耗尽它们。

NSString *iAmAstring;
for(int i = 0; i < 100000;i++)
{
    @autoreleasepool {
         NSLog(@"INT VALUE: %d", i);
        iAmAstring = [NSString stringWithFormat:@"%d", i];
        NSLog(@"STRING VALUE: %@", iAmAstring);
    }
}

这将耗尽自动释放池并在循环的每次迭代中释放所有自动释放的对象。这对于细小的字符串是一件很浪费的事情,但对于较大的对象可能会有很大的帮助。

release关于自动释放如何工作的快速说明:它所做的只是在池耗尽时给你的对象一个额外的调用。默认池在事件循环中耗尽(即在您的方法退出后的某个时间)。当范围@autoreleasepool结束时,您手动创建的池将被耗尽。

我最初来自 C# 背景,我习惯于在循环结束时将我的字符串设置为 null

除非您稍后重新使用该变量,否则这会在您的程序中添加完全无用的代码行:C# 编译器已经足够聪明一段时间了,可以找出让您的对象可用于垃圾回收的最早点,因此分配null没有帮助。

于 2012-07-25T04:59:13.727 回答
0

我永远不明白的是为什么人们认为他们需要使用自动释放池而不是仅仅使用 alloc/init 来创建他们的对象并显式释放来处理它们。

有一些具有副作用的对象需要自动释放池(日期,我在看你),但在大多数情况下,做

{
    NSString *s = [[NSString alloc] initWithFormat:...];
    ....
    [s release];
}

在您的循环中将比依赖自动释放更有效。

关于场景 2,抱歉, NSString 是不可变的 - 您不会更改它们的值。

于 2012-07-25T07:38:58.790 回答