错误的编码延迟初始化效果很好

时间:2011-06-07 09:14:40

标签: objective-c return-value lazy-initialization

故意是错误编码的懒惰初始化:

-(X*) prop {
    if (!prop) {
        prop = [[Prop alloc] init];
        return prop;
    }
    // RETURN SHOULD BE HERE 
}

然而,由于下面生成的代码序列,它做了“正确的事情”吗?

  • 将道具装入rax进行测试
  • 无论如何返回rax

2 个答案:

答案 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)

  

故意是错误编码的懒惰初始化:

没有

您很幸运,使用了标准的返回寄存器。永远不要依赖它。实际上,它应该给你一个编译器警告。