Ios ARC和自动释放

Ios ARC和自动释放,ios,objective-c,memory-management,automatic-ref-counting,reference-counting,Ios,Objective C,Memory Management,Automatic Ref Counting,Reference Counting,autorelease用于返回的函数对象,因此调用者不拥有所有权,被调用者将在将来释放该对象 但是,ARC能够计算调用方的所有权并在使用后释放它,也就是说,它可以像C++中的Smart Pointer一样运行。有了ARC,它可以摆脱自动释放,因为自动释放是不确定的 我问这个问题的原因是,我确实看到返回的对象在ARC中调用dealloc比在非ARC代码中更早。这让我觉得ARC可以像智能指针一样,让自动释放变得毫无用处。这是真的还是可能的?我唯一能想到的关于自动释放的有用性是在多线程或网络代码中,因

autorelease用于返回的函数对象,因此调用者不拥有所有权,被调用者将在将来释放该对象

但是,ARC能够计算调用方的所有权并在使用后释放它,也就是说,它可以像C++中的Smart Pointer一样运行。有了ARC,它可以摆脱自动释放,因为自动释放是不确定的

我问这个问题的原因是,我确实看到返回的对象在ARC中调用dealloc比在非ARC代码中更早。这让我觉得ARC可以像智能指针一样,让自动释放变得毫无用处。这是真的还是可能的?我唯一能想到的关于自动释放的有用性是在多线程或网络代码中,因为当对象传递时,计算所有权可能并不容易

谢谢你的想法

下面是一个新的编辑,让事情变得更清楚:

自动释放

+ (MyClass*) myClass
{
    return [[[MyCClass alloc] init] autorelease];
}

- doSomething
{
   MyClass *obj = [MyClass myClass];
}
使用ARC时:

+ (MyClass*) myClass
{
    return [[MyCClass alloc] init]; // no autorelease
}

- doSomething
{
   MyClass *obj = [MyClass myClass];
   // insert [obj release]
}

所以,我们真的不需要自动释放。

代码中解释了ARC和自动释放之间的区别:

弧:

自动释放:

-somefunc {
  id obj = [NSArray array];
  NSLog(@"%@", obj);

  id obj2 = [NSArray array];
  NSLog(@"%@", obj2);
}
// Objects are released some time after this

基本上,只要变量不再在作用域中使用,ARC就会工作,而autorelease则会等待它到达主循环,然后对池中的所有对象调用
release
。ARC在范围内使用,自动释放在功能范围外使用。

自动释放作为一种机制仍由ARC使用,而且ARC编译代码设计为与MRC编译代码无缝互操作,因此自动释放机制就在身边

首先,不要从参考的角度来思考,而是从所有权利益的角度来思考——只要一个对象中有一个声明的所有权利益,那么该对象就存在,当没有所有权利益时,它就会被销毁。在MRC中,您可以通过使用
retain
或创建新对象来声明所有权权益;您可以通过使用
release
放弃所有权权益

现在,当被调用者方法创建一个对象并希望将其返回给调用者时,被调用者正在离开,因此它需要放弃所有权权益,因此调用者需要声明其所有权权益,否则该对象可能会被销毁。但是有一个问题,被调用方在调用方接收对象之前完成-因此,当调用方放弃其所有权权益时,对象可能在调用方有机会声明其权益之前被销毁-不好

有两种解决方案可用于解决此问题:

1) 该方法被声明为将其返回值中的所有权权益从被调用方转移到调用方-这是用于
init
copy
等方法的模型。被呼叫者从未通知它正在放弃其所有权权益,被呼叫者也从未声明所有权权益-根据协议,呼叫者只是接管所有权权益并承担稍后放弃的责任

2) 该方法被声明为返回一个值,在该值中调用方没有所有权权益,但其他人将在一段短时间内保持所有权权益,通常直到当前运行循环周期结束。如果调用方希望使用返回值的时间长于此值,则必须声明其自己的所有权权益,否则它可以依赖拥有所有权权益的其他人,因此对象将留在附近

问题是谁能成为维护所有权权益的“某人”?它不能是被调用方方法,因为它即将消失。进入“自动释放池”-这只是一个任何人都可以将所有权权益转移到的对象,因此该对象将保留一段时间。自动释放池在接到指示时,通常在当前运行循环周期结束时,将放弃其对以这种方式传输给它的所有对象的所有权权益

现在,如果上述内容有任何意义(即,如果我解释得很清楚),您可以看到方法(2)并不是真正需要的,因为您可以始终使用方法(1);但是,这是一个关键的问题,但是,在MRC下,程序员需要做更多的工作——从方法接收到的每个值都有一个所有权权益,必须在某个时候进行管理和放弃——生成一个字符串来输出它?那么你就需要放弃你对这个临时字符串的兴趣。。。所以(2)让生活变得容易多了

另一方面,计算机只是快速的白痴,计算东西和插入代码以代表智能程序员放弃所有权是他们非常适合的事情。所以ARC不需要自动释放池。但它可以使事情变得更简单、更高效,并且幕后ARC优化了它的使用——看看Xcode中的汇编程序输出,您将看到对名为“RetainUserReleasedReturnValue”的例程的调用

所以你是对的,它不需要,但是它仍然有用——但是在ARC下,你可以(通常)忘记它的存在

比它可能混淆的还要多

autorelease用于返回的函数对象,因此调用者不拥有所有权,被调用者将在将来释放该对象

如果自动释放,它将被添加到自动释放池中。当自动释放池排空时,将执行延迟释放。函数/方法不需要返回自动释放对象(例如,它可能是未接收保留/自动释放循环的ivar)

但是,ARC能够计算调用方的所有权并在使用后释放它,也就是说,它可以像C++中的Smart Pointer一样运行。有了ARC,它可以摆脱自动释放,因为自动释放是不确定的

它有可能实现这一目标。没有保证。这里最大的“问题”是编译器不知道/不关心任意调用返回对象的内存机制。它不能假设对象是如何返回的,因为ARC是MRC之前的新添加项。这很重要,因为它使ARC程序与progr兼容
-somefunc {
  id obj = [NSArray array];
  NSLog(@"%@", obj);

  id obj2 = [NSArray array];
  NSLog(@"%@", obj2);
}
// Objects are released some time after this
void foo() {
    @autoreleasepool {
        NSNumber *number = [NSNumber numberWithInt:0];
        NSLog(@"number = %p", number);
    }
}
    .globl  _foo
    .align  2
    .code   16
    .thumb_func     _foo
_foo:
    push    {r4, r7, lr}
    add     r7, sp, #4
    blx     _objc_autoreleasePoolPush
    movw    r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_-(LPC0_0+4))
    movs    r2, #0
    movt    r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_-(LPC0_0+4))
    mov     r4, r0
    movw    r0, :lower16:(L_OBJC_CLASSLIST_REFERENCES_$_-(LPC0_1+4))
LPC0_0:
    add     r1, pc
    movt    r0, :upper16:(L_OBJC_CLASSLIST_REFERENCES_$_-(LPC0_1+4))
LPC0_1:
    add     r0, pc
    ldr     r1, [r1]
    ldr     r0, [r0]
    blx     _objc_msgSend
    mov     r1, r0
    movw    r0, :lower16:(L__unnamed_cfstring_-(LPC0_2+4))
    movt    r0, :upper16:(L__unnamed_cfstring_-(LPC0_2+4))
LPC0_2:
    add     r0, pc
    blx     _NSLog
    mov     r0, r4
    blx     _objc_autoreleasePoolPop
    pop     {r4, r7, pc}
    .globl  _foo
    .align  2
    .code   16
    .thumb_func     _foo
_foo:
    push    {r4, r5, r7, lr}
    add     r7, sp, #8
    blx     _objc_autoreleasePoolPush
    movw    r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_-(LPC0_0+4))
    movs    r2, #0
    movt    r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_-(LPC0_0+4))
    mov     r4, r0
    movw    r0, :lower16:(L_OBJC_CLASSLIST_REFERENCES_$_-(LPC0_1+4))
LPC0_0:
    add     r1, pc
    movt    r0, :upper16:(L_OBJC_CLASSLIST_REFERENCES_$_-(LPC0_1+4))
LPC0_1:
    add     r0, pc
    ldr     r1, [r1]
    ldr     r0, [r0]
    blx     _objc_msgSend
    @ InlineAsm Start
    mov     r7, r7          @ marker for objc_retainAutoreleaseReturnValue
    @ InlineAsm End
    blx     _objc_retainAutoreleasedReturnValue
    mov     r5, r0
    movw    r0, :lower16:(L__unnamed_cfstring_-(LPC0_2+4))
    movt    r0, :upper16:(L__unnamed_cfstring_-(LPC0_2+4))
    mov     r1, r5
LPC0_2:
    add     r0, pc
    blx     _NSLog
    mov     r0, r5
    blx     _objc_release
    mov     r0, r4
    blx     _objc_autoreleasePoolPop
    pop     {r4, r5, r7, pc}
void bar() {
    NSNumber *number;
    @autoreleasepool {
        number = [NSNumber numberWithInt:0];
        NSLog(@"number = %p", number);
    }
    NSLog(@"number = %p", number);
}
    .globl  _bar
    .align  2
    .code   16
    .thumb_func     _bar
_bar:
    push    {r4, r5, r6, r7, lr}
    add     r7, sp, #12
    blx     _objc_autoreleasePoolPush
    movw    r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_-(LPC1_0+4))
    movs    r2, #0
    movt    r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_-(LPC1_0+4))
    mov     r4, r0
    movw    r0, :lower16:(L_OBJC_CLASSLIST_REFERENCES_$_-(LPC1_1+4))
LPC1_0:
    add     r1, pc
    movt    r0, :upper16:(L_OBJC_CLASSLIST_REFERENCES_$_-(LPC1_1+4))
LPC1_1:
    add     r0, pc
    ldr     r1, [r1]
    ldr     r0, [r0]
    blx     _objc_msgSend
    movw    r6, :lower16:(L__unnamed_cfstring_-(LPC1_2+4))
    movt    r6, :upper16:(L__unnamed_cfstring_-(LPC1_2+4))
LPC1_2:
    add     r6, pc
    mov     r5, r0
    mov     r1, r5
    mov     r0, r6
    blx     _NSLog
    mov     r0, r4
    blx     _objc_autoreleasePoolPop
    mov     r0, r6
    mov     r1, r5
    blx     _NSLog
    pop     {r4, r5, r6, r7, pc}
    .globl  _bar
    .align  2
    .code   16
    .thumb_func     _bar
_bar:
    push    {r4, r5, r6, r7, lr}
    add     r7, sp, #12
    blx     _objc_autoreleasePoolPush
    movw    r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_-(LPC1_0+4))
    movs    r2, #0
    movt    r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_-(LPC1_0+4))
    mov     r4, r0
    movw    r0, :lower16:(L_OBJC_CLASSLIST_REFERENCES_$_-(LPC1_1+4))
LPC1_0:
    add     r1, pc
    movt    r0, :upper16:(L_OBJC_CLASSLIST_REFERENCES_$_-(LPC1_1+4))
LPC1_1:
    add     r0, pc
    ldr     r1, [r1]
    ldr     r0, [r0]
    blx     _objc_msgSend
    @ InlineAsm Start
    mov     r7, r7          @ marker for objc_retainAutoreleaseReturnValue
    @ InlineAsm End
    blx     _objc_retainAutoreleasedReturnValue
    movw    r6, :lower16:(L__unnamed_cfstring_-(LPC1_2+4))
    movt    r6, :upper16:(L__unnamed_cfstring_-(LPC1_2+4))
LPC1_2:
    add     r6, pc
    mov     r5, r0
    mov     r1, r5
    mov     r0, r6
    blx     _NSLog
    mov     r0, r4
    blx     _objc_autoreleasePoolPop
    mov     r0, r6
    mov     r1, r5
    blx     _NSLog
    mov     r0, r5
    blx     _objc_release
    pop     {r4, r5, r6, r7, pc}