で、結局ARCってなんなの?
GCとARC何か似てるようなものと思っていませんか?
ARCもGCみたく実行時に変なウエイトが掛かるんじゃないの?とか。
実際は全く別物です。
結論を先に言えばCGは動的メモリ管理、ARCは静的メモリ管理です。
静的--つまりコンパイル時にメモリを管理しちゃうんですね。
じゃあ、見てみましょ。
#import <Foundation/Foundation.h> int main( int argc, char *argv[]) { id obj = [NSString stringWithString:@"hoge"]; fprintf(stderr, "%s\n", [obj UTF8String]); return 0; }
特に意味のあるコードではありません。これのアセンブラコードを見てみましょ。
ARCだとこうなります。
$ cc -fobjc-arc -S -o foo.arc.s foo.m
(snip) _main: ## @main Ltmp2: .cfi_startproc ## BB#0: pushq %rbp Ltmp3: .cfi_def_cfa_offset 16 Ltmp4: .cfi_offset %rbp, -16 movq %rsp, %rbp Ltmp5: .cfi_def_cfa_register %rbp subq $64, %rsp leaq L__unnamed_cfstring_(%rip), %rax movl $0, -4(%rbp) movl %edi, -8(%rbp) movq %rsi, -16(%rbp) movq L_OBJC_CLASSLIST_REFERENCES_$_(%rip), %rsi movq L_OBJC_SELECTOR_REFERENCES_(%rip), %rcx movq %rsi, %rdi movq %rcx, %rsi movq %rax, %rdx callq _objc_msgSend movq %rax, %rdi callq _objc_retainAutoreleasedReturnValue ## ここ注目! movq ___stderrp@GOTPCREL(%rip), %rcx movq %rax, -24(%rbp) movq (%rcx), %rdi movq -24(%rbp), %rax movq %rdi, -40(%rbp) ## 8-byte Spill movq %rax, %rdi callq _objc_retainAutorelease ## ここ注目! leaq L_.str1(%rip), %rsi movq L_OBJC_SELECTOR_REFERENCES_3(%rip), %rcx movq %rax, %rdi movq %rsi, -48(%rbp) ## 8-byte Spill movq %rcx, %rsi callq _objc_msgSend movq -40(%rbp), %rdi ## 8-byte Reload movq -48(%rbp), %rsi ## 8-byte Reload movq %rax, %rdx movb $0, %al callq _fprintf movl $0, -4(%rbp) movl $1, -28(%rbp) movq -24(%rbp), %rdi movl %eax, -52(%rbp) ## 4-byte Spill callq _objc_release # ここ注目! movl -4(%rbp), %eax addq $64, %rsp popq %rbp ret Ltmp6: .cfi_endproc Leh_func_end0: (snip)
ここ注目!と書いた所に注目!
あれ? リファレンスカウンタ使ってね?
そう、その通り。GC的なメモリ管理ではなくて普通にretain, release, autoreleaseを使ったリファレンスカウンタ方式でメモリ管理してるんですね。
つまり、ARC--Automatic Reference Counting--の名前の通りなんです。自動で勝手にリファレンスカウンタ方式でメモリ管理してるんです。
これのメリットは2つ。
1、releaseとかretainとかautoreleaseとか打たなくていいからラクチン!
2、解放し過ぎも解放忘れも起こりません!
1は副次的なもので2が目的だと思います。