__strong修飾符

本文用來觀察,對於__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方法

相關文章
相關標籤/搜索