Ios 为什么在没有@autoreleasepool的情况下,在for循环的每个周期中都使用NSString自动释放

Ios 为什么在没有@autoreleasepool的情况下,在for循环的每个周期中都使用NSString自动释放,ios,objective-c,Ios,Objective C,这是我的测试代码: for (int i = 0; i < 1000000000; ++i) { NSString *string = @"Abc"; string = [string lowercaseString]; string = [string stringByAppendingString:@"xyz"]; } 还返回一个自动释放对象。我对此感到困惑…使用ARC编译的代码必须与未使用ARC编译的代码进行互操作。此外,你不能假设基础,特别是你调用的 NS

这是我的测试代码:

for (int i = 0; i < 1000000000; ++i) {
    NSString *string = @"Abc";
    string = [string lowercaseString];
    string = [string stringByAppendingString:@"xyz"];
}

还返回一个自动释放对象。我对此感到困惑…

使用ARC编译的代码必须与未使用ARC编译的代码进行互操作。此外,你不能假设基础,特别是你调用的<代码> NScord的方法是用ARC.< 那些
NSString
方法的编译方式必须确保可以从ARC和非ARC代码调用它们。这意味着它们必须自动释放它们返回的对象,不管它们本身是否使用ARC编译

但是,如果那些
NSString
方法是使用ARC编译的,那么它们可以使用
objc\u autoreleaserentvalue()
来执行自动删除。如果调用方也是使用ARC编译的,并且它保留了对象(例如,因为它被赋给了一个强局部变量),那么它可能会对其使用
objc_retainAutoreleasedReturnValue()
。在这种情况下,可以避免使用自动释放池
objc_autoreleaseReturnValue()
可以通过检查堆栈和调用者的指令来检测调用者是否会对返回的值使用
objc_retainutoreleasedreturnvalue()
,它不会自动删除该值,而是通过一个侧通道将该事实传达给
objc_retainutoreleasedreturnvalue()
这样它就不会保留该值

所以,在某些特定的情况下,您不能依靠自己来决定,那些“正常”自动释放然后保留对象的代码将不会。它只会转移所有权

ARC不会自动排空自动释放池或引入内部自动释放池

由于存在不确定性,您应该始终使用
@autoreleasepool
来处理任何可能由于自动释放对象而占用内存的代码。例如:

for (int i = 0; i < 1000000000; ++i) @autoreleasepool {
    NSString *string = @"Abc";
    string = [string lowercaseString];
    string = [string stringByAppendingString:@"xyz"];
}
(int i=0;i<100000000;++i)@autoreleasepool的
{
NSString*string=@“Abc”;
字符串=[字符串小写字符串];
字符串=[string stringByAppendingString:@“xyz”];
}

是的,ARC内存管理是自动化的。但它并不总是以正确的方式行事。尤其是在创建许多临时对象的循环中

临时对象是仅在当前迭代中创建和使用的对象。类似于附加到较大字符串的小字符串

这些临时对象在循环完成后被释放,这可能太晚了。这就是为什么必须将循环体放入
@autoreleasepool
中,以确保每次循环迭代后立即释放对象

for (int i = 0; i < 1000000000; ++i) {
    @autoreleasepool {
        NSString *string = [NSString stringWithFormat:@"aaaaaaaaaaaaaaaaaaa"];
    }
}
for(int i=0;i<100000000;++i){
@自动释放池{
NSString*string=[NSString stringWithFormat:@“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;
}
}

进一步阅读:

使用ARC,编译器变得更加智能

在ARC之前,lowercaseString等方法将创建一个保留/自动释放对象,并将其放入自动释放池中。使用ARC,编译器是智能的:小写字符串检查调用它的方法是否立即保留结果。在这种情况下,您将有一个retain/autorelease/retain序列,在这种情况下,小写字符串根本不能执行retain/autorelease,因此只执行调用者的retain。这会更快(它会保存一个retain和一个autorelease,并在autorelease池关闭时保存最终版本),并且autorelease池不会过度增长


也就是说,只有编译器执行优化才能工作的代码被破坏了

等等,你想手动完成吗?ARC是4年前出现的。我建议您保持启用状态。它在引擎盖下处理内存管理,因此您不必自动释放或完全释放自己。如果您在非arc环境中使用它,它会爆炸的原因是因为您没有释放任何内存。每个循环不断占用空间。在ARC中,它是自动处理的。有隐式(隐藏的)自动释放池和对自动释放的调用,因此它会自动发生在引擎盖下。ARC可能会插入一个-release,而不是一个-autorelease(如果可以)。一种知道的方法是检查反汇编。不,不,我在工作中使用ARC,我只想知道原因。@ArtSabintsev“temp objects”?你不能说得更准确些吗?我加了一段简短的解释。我希望你把它们称为
autorelease
而不是“temp”。非常感谢。这对我帮助很大。
for (int i = 0; i < 1000000000; ++i) @autoreleasepool {
    NSString *string = @"Abc";
    string = [string lowercaseString];
    string = [string stringByAppendingString:@"xyz"];
}
for (int i = 0; i < 1000000000; ++i) {
    @autoreleasepool {
        NSString *string = [NSString stringWithFormat:@"aaaaaaaaaaaaaaaaaaa"];
    }
}