意図的にコード化された怠惰な初期化:
-(X*) prop {
if (!prop) {
prop = [[Prop alloc] init];
return prop;
}
// RETURN SHOULD BE HERE
}
それにもかかわらず、以下の生成されたコードシーケンスによる「正しいこと」はありますか?
- テストのために prop を rax にロードする
- いずれにせよraxを返す
意図的にコード化された怠惰な初期化:
-(X*) prop {
if (!prop) {
prop = [[Prop alloc] init];
return prop;
}
// RETURN SHOULD BE HERE
}
それにもかかわらず、以下の生成されたコードシーケンスによる「正しいこと」はありますか?
これは意図的なものではありません。たとえうまくいったとしても、それに頼るべきではありません。たとえば、次のことを考慮してください。
- (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 を遅延して初期化する呼び出し) では機能しますが、2 回目の呼び出しではクラッシュします。
意図的に、コード化されていない遅延初期化:
いいえ。
標準リターンレジスタが使用されたのは幸運です。絶対に頼らないでください。実際、コンパイラの警告が表示されるはずです。