本文用來觀察,對於__strong修飾符,編譯器爲咱們自動添加了什麼代碼,這些代碼對於引用計數有什麼影響。spa
例子一code
X __strong *x1 = [[X alloc] init];
使用控制檯打印引用計數,計數值爲1,符合預期:對象
(lldb) p CFGetRetainCount((__bridge CFTypeRef)x1) (CFIndex) $0 = 1 (lldb)
例子二blog
X __strong *x2 = [X create]; //create返回對象X
使用控制檯查看引用計數,計數值爲2:ip
(lldb) p CFGetRetainCount((__bridge CFTypeRef)x2) (CFIndex) $1 = 2 (lldb)
計數值爲2,說明x2被持有了兩次,使用clang的-S選項查看彙編文件:編譯器
.loc 1 40 7 is_stmt 0 ## autorelease.m:40:7 調用[X create]的源碼處 movq %rax, %rdi callq _objc_retainAutoreleasedReturnValue ##返回的autoreleased值被又持有了一次 xorl %ecx, %ecx movl %ecx, %esi movq %rax, -24(%rbp)
發現編譯器對於返回的autoreleased值(即由非alloc/new/init/copy/mutableCopy開頭的方法返回的值)調用了一次Retain方法。源碼
例子三it
X __storng *x1 = [[X alloc] init];
X __strong *x2 = x1;
在Xcode控制檯查看引用計數,結果爲2,說明對__strong變量賦值操做,也會致使引用計數加1:編譯
(lldb) p CFGetRetainCount((__bridge CFTypeRef)x1) (CFIndex) $2 = 2 (lldb) p CFGetRetainCount((__bridge CFTypeRef)x2) (CFIndex) $3 = 2 (lldb)
查看彙編代碼,發現賦值操做編譯器也會自動插入Retian操做:table
.loc 1 40 7 ## autorelease.m:40:7 調用[[X alloc] init]處 movq %rax, -24(%rbp) .loc 1 41 12 is_stmt 1 ## autorelease.m:41:12 x2 = x1處 movq -24(%rbp), %rax movq %rax, %rdi callq *_objc_retain@GOTPCREL(%rip) ##賦值的時候,也會調用Retian方法
總結
對於__strong修飾符,編譯器會根據狀況插入Retain方法:
1 若是是alloc/init/new/copy/mutableCopy方法或者以他們做爲方法名開頭的方法來給__strong變量賦值,編譯器不會插入Retain方法
2 若是是非1所指的方法,或者是把一個變量賦給一個__strong變量,編譯器都會插入相應的Retain方法