Разница невелика, но вы должны выбрать версии 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
и 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}
b.w _objc_autorelease