故意是错误编码的懒惰初始化:
-(X*) prop {
if (!prop) {
prop = [[Prop alloc] init];
return prop;
}
// RETURN SHOULD BE HERE
}
然而,由于下面生成的代码序列,它做了“正确的事情”吗?
答案 0 :(得分:4)
这不是故意的,即使它有效,你也不应该依赖它。例如,请考虑以下事项:
- (NSString *)someString {
if (! someString) {
someString = [[NSString alloc] initWithFormat:@"%d", 5];
return someString;
}
}
使用gcc -O0
编译时:
movq -24(%rbp), %rdx
movq _OBJC_IVAR_$_SomeClass.someString@GOTPCREL(%rip), %rax
movq (%rax), %rax
leaq (%rdx,%rax), %rax
movq (%rax), %rax
testq %rax, %rax
并且代码确实有效,因为正如您所注意到的那样,ivar被加载到RAX
。
但是,使用gcc -O3
进行编译时:
movq %rdi, %rbx
addq _OBJC_IVAR_$_SomeClass.someString(%rip), %rbx
cmpq $0, (%rbx)
je L5
L4:
movq (%rsp), %rbx
movq 8(%rsp), %r12
糟糕,RAX
中没有返回值 - 将ivar加载到RBX
。此代码在第一次调用(懒惰地初始化ivar)中起作用,但在第二次调用中崩溃。
答案 1 :(得分:2)
故意是错误编码的懒惰初始化:
没有
您很幸运,使用了标准的返回寄存器。永远不要依赖它。实际上,它应该给你一个编译器警告。