Ios ARC和自动释放
autorelease用于返回的函数对象,因此调用者不拥有所有权,被调用者将在将来释放该对象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可以像智能指针一样,让自动释放变得毫无用处。这是真的还是可能的?我唯一能想到的关于自动释放的有用性是在多线程或网络代码中,因
但是,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}