差异是微妙的,但您应该选择autorelease
版本。首先,您的代码更具可读性。其次,在检查优化的装配输出时,autorelease
版本稍微更优化。
autorelease
版本,
- (NSString *)hello:(NSString *)name {
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}
而 [[alloc] init] 版本如下所示:
"-[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
正如预期的那样,它有点长,因为它正在调用alloc
andinitWithFormat:
方法。特别有趣的是 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}
b.w _objc_autorelease