使用ARC,更好的是:alloc或autorelease initializers? [英] With ARC, what's better: alloc or autorelease initializers?

查看:165
本文介绍了使用ARC,更好的是:alloc或autorelease initializers?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 alloc autorelease 初始化程序更好(更快,更高效)。例如:

   - (NSString *)hello:(NSString *)name {
return [[NSString alloc] initWithFormat :@Hello,%@,name];
}

   - (NSString *)hello:(NSString *)name {
return [NSString stringWithFormat:@Hello,%@,name];
// return [@Hello,stringByAppendingString:name]; //甚至更简单
}

我知道在大多数情况下,物。但是,我仍然想要做更好的方式的习惯。



如果他们做同样的事情,那么我更喜欢后一个选项,因为它更短的类型和更可读。



在Xcode 4.2中,有一种方法看看ARC编译,即,它放置 / code>, release autorelease 此功能在切换到ARC时非常有用。我知道你不应该考虑这些东西,但它会帮助我找出这样的问题的答案。

解决方案

区别很微妙,但您应该选择 autorelease 版本。首先,你的代码更加可读。其次,在检查优化的汇编输出时, autorelease 版本稍微更优化。



$ c> autorelease 版本,

   - (NSString *)hello: 
return [NSString stringWithFormat:@Hello,%@,name];
}

翻译为

  -  [SGCAppDelegate hello:]:
push {r7,lr}
movw r1,:lower16:(L_OBJC_SELECTOR_REFERENCES _-(LPC0_0 + 4))
mov r3,r2
movt r1,:upper16:(L_OBJC_SELECTOR_REFERENCES _-(LPC0_0 + 4))
movw r0,:lower16:(L_OBJC_CLASSLIST_REFERENCES _ $ _-(LPC0_1 + 4))
movt r0,:upper16:(L_OBJC_CLASSLIST_REFERENCES _ $ _-(LPC0_1 + 4))
add r1,pc
add r0,pc
mov r7,sp
ldr r1,[r1 ]
ldr r0,[r0]
movw r2,:lower16:(L__unnamed_cfstring _-(LPC0_2 + 4))
movt r2,:upper16:(L__unnamed_cfstring _-(LPC0_2 + 4))
add r2,pc
blx _objc_msgSend; stringWithFormat:
pop {r7,pc}

如下:

  -  [SGCAppDelegate hello:]:
push {r4,r5,r6, r7,lr}
movw r1,:lower16:(L_OBJC_SELECTOR_REFERENCES_2-(LPC1_0 + 4))
add r7,sp,#12
movt r1,:upper16:(L_OBJC_SELECTOR_REFERENCES_2- 4))
movw r0,:lower16:(L_OBJC_CLASSLIST_REFERENCES _ $ _-(LPC1_1 + 4))
movt r0,:upper16:(L_OBJC_CLASSLIST_REFERENCES _ $ _-(LPC1_1 + 4))
add r1,pc
add r0,pc
ldr r5,[r1]
ldr r6,[r0]
mov r0,r2
blx _objc_retain; ARC暂时保留名称字符串
mov r1,r5
mov r4,r0
mov r0,r6
blx _objc_msgSend;调用alloc
movw r1,:lower16:(L_OBJC_SELECTOR_REFERENCES_4-(LPC1_2 + 4))
mov r3,r4
movt r1,:upper16:(L_OBJC_SELECTOR_REFERENCES_4- b $ b add r1,pc
ldr r1,[r1]
movw r2,:lower16:(L__unnamed_cfstring _-(LPC1_3 + 4))
movt r2,:upper16:(L__unnamed_cfstring _- LPC1_3 + 4))
add r2,pc
blx _objc_msgSend;调用initWithFormat:
mov r5,r0
mov r0,r4
blx _objc_release; ARC释放名称string
mov r0,r5
pop.w {r4,r5,r6,r7,lr}
bw _objc_autorelease
pre>

正如预期,它是一个更长的时间,因为它正在调用 alloc initWithFormat:方法。特别有趣的是,ARC在这里生成次优代码,因为它保留了 name 字符串(通过调用_objc_retain标注),并且稍后在调用 initWithFormat:



如果我们添加 __ unsafe_unretained 所有权限定符,如下面的示例所示,代码将被最佳地呈现。 __ unsafe_unretained 指示编译器使用原语(复制指针)分配语义

   - (NSString *)hello:(__ unsafe_unretained NSString *)name {
return [[NSString alloc] initWithFormat:@Hello,%@,name];
}

,如下所示:

  -  [SGCAppDelegate hello:]:
push {r4,r7,lr}
movw r1,:lower16:(L_OBJC_SELECTOR_REFERENCES_2-(LPC1_0 + 4) )
add r7,sp,#4
movt r1,:upper16:(L_OBJC_SELECTOR_REFERENCES_2-(LPC1_0 + 4))
movw r0,:lower16:(L_OBJC_CLASSLIST_REFERENCES _ $ _-(LPC1_1 + 4 ))
movt r0,:upper16:(L_OBJC_CLASSLIST_REFERENCES _ $ _-(LPC1_1 + 4))
add r1,pc
add r0,pc
mov r4,r2
ldr r1,[r1]
ldr r0,[r0]
blx _objc_msgSend
movw r1,:lower16:(L_OBJC_SELECTOR_REFERENCES_4-(LPC1_2 + 4))
mov r3,r4
movt r1,:upper16:(L_OBJC_SELECTOR_REFERENCES_4-(LPC1_2 + 4))
add r1,pc
ldr r1,[r1]
movw r2,:lower16:(L__unnamed_cfstring_- (LPC1_3 + 4))
movt r2,:upper16:(L__unnamed_cfstring _-(LPC1_3 + 4))
add r2,pc
blx _objc_msgSend
.loc 1 31 1
pop.w {r4,r7,lr}
bw _objc_autorelease


Is it better (faster & more efficient) to use alloc or autorelease initializers. E.g.:

- (NSString *)hello:(NSString *)name {
    return [[NSString alloc] initWithFormat:@"Hello, %@", name];
}

OR

- (NSString *)hello:(NSString *)name {
    return [NSString stringWithFormat:@"Hello, %@", name];
//    return [@"Hello, " stringByAppendingString:name]; // even simpler
}

I know that in most cases, performance here shouldn't matter. But, I'd still like to get in the habit of doing it the better way.

If they do exactly the same thing, then I prefer the latter option because it's shorter to type and more readable.

In Xcode 4.2, is there a way to see what ARC compiles to, i.e., where it puts retain, release, autorelease, etc? This feature would be very useful while switching over to ARC. I know you shouldn't have to think about this stuff, but it'd help me figure out the answer to questions like these.

解决方案

The difference is subtle, but you should opt for the autorelease versions. Firstly, your code is much more readable. Secondly, on inspection of the optimized assembly output, the autorelease version is slightly more optimal.

The autorelease version,

- (NSString *)hello:(NSString *)name {
    return [NSString stringWithFormat:@"Hello, %@", name];
}

translates to

"-[SGCAppDelegate hello:]":
    push    {r7, lr}
    movw    r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_-(LPC0_0+4))
    mov r3, r2
    movt    r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_-(LPC0_0+4))
    movw    r0, :lower16:(L_OBJC_CLASSLIST_REFERENCES_$_-(LPC0_1+4))
    movt    r0, :upper16:(L_OBJC_CLASSLIST_REFERENCES_$_-(LPC0_1+4))
    add r1, pc
    add r0, pc
    mov r7, sp
    ldr r1, [r1]
    ldr r0, [r0]
    movw    r2, :lower16:(L__unnamed_cfstring_-(LPC0_2+4))
    movt    r2, :upper16:(L__unnamed_cfstring_-(LPC0_2+4))
    add r2, pc
    blx _objc_msgSend    ; stringWithFormat:
    pop {r7, pc}

Whereas the [[alloc] init] version looks like the following:

"-[SGCAppDelegate hello:]":
    push    {r4, r5, r6, r7, lr}
    movw    r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_2-(LPC1_0+4))
    add r7, sp, #12
    movt    r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_2-(LPC1_0+4))
    movw    r0, :lower16:(L_OBJC_CLASSLIST_REFERENCES_$_-(LPC1_1+4))
    movt    r0, :upper16:(L_OBJC_CLASSLIST_REFERENCES_$_-(LPC1_1+4))
    add r1, pc
    add r0, pc
    ldr r5, [r1]
    ldr r6, [r0]
    mov r0, r2
    blx _objc_retain    ; ARC retains the name string temporarily
    mov r1, r5
    mov r4, r0
    mov r0, r6
    blx _objc_msgSend   ; call to alloc
    movw    r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_4-(LPC1_2+4))
    mov r3, r4
    movt    r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_4-(LPC1_2+4))
    add r1, pc
    ldr r1, [r1]
    movw    r2, :lower16:(L__unnamed_cfstring_-(LPC1_3+4))
    movt    r2, :upper16:(L__unnamed_cfstring_-(LPC1_3+4))
    add r2, pc
    blx _objc_msgSend   ; call to initWithFormat:
    mov r5, r0
    mov r0, r4
    blx _objc_release   ; ARC releases the name string
    mov r0, r5
    pop.w   {r4, r5, r6, r7, lr}
    b.w _objc_autorelease

As expected, it is a little longer, because it is calling the alloc and initWithFormat: methods. What is particularly interesting is ARC is generating sub-optimal code here, as it retains the name string (noted by call to _objc_retain) and later released after the call to initWithFormat:.

If we add the __unsafe_unretained ownership qualifier, as in the following example, the code is rendered optimally. __unsafe_unretained indicates to the compiler to use primitive (copy pointer) assignment semantics.

- (NSString *)hello:(__unsafe_unretained NSString *)name {
    return [[NSString alloc] initWithFormat:@"Hello, %@", name];
}

as follows:

"-[SGCAppDelegate hello:]":
    push    {r4, r7, lr}
    movw    r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_2-(LPC1_0+4))
    add r7, sp, #4
    movt    r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_2-(LPC1_0+4))
    movw    r0, :lower16:(L_OBJC_CLASSLIST_REFERENCES_$_-(LPC1_1+4))
    movt    r0, :upper16:(L_OBJC_CLASSLIST_REFERENCES_$_-(LPC1_1+4))
    add r1, pc
    add r0, pc
    mov r4, r2
    ldr r1, [r1]
    ldr r0, [r0]
    blx _objc_msgSend
    movw    r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_4-(LPC1_2+4))
    mov r3, r4
    movt    r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_4-(LPC1_2+4))
    add r1, pc
    ldr r1, [r1]
    movw    r2, :lower16:(L__unnamed_cfstring_-(LPC1_3+4))
    movt    r2, :upper16:(L__unnamed_cfstring_-(LPC1_3+4))
    add r2, pc
    blx _objc_msgSend
    .loc    1 31 1
    pop.w   {r4, r7, lr}
    b.w _objc_autorelease

这篇关于使用ARC,更好的是:alloc或autorelease initializers?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆