__strong修饰符

本文用来观察,对于__strong修饰符,编译器为我们自动添加了什么代码,这些代码对于引用计数有什么影响。

例子一

X __strong *x1 = [[X alloc] init];

使用控制台打印引用计数,计数值为1,符合预期:

(lldb) p CFGetRetainCount((__bridge CFTypeRef)x1)
(CFIndex) $0 = 1
(lldb) 

例子二

X __strong *x2 = [X create]; //create返回对象X

使用控制台查看引用计数,计数值为2:

(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方法。

例子三

 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操作:

.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    *[email protected](%rip)  ##赋值的时候,也会调用Retian方法

总结

对于__strong修饰符,编译器会根据情况插入Retain方法:

1 如果是alloc/init/new/copy/mutableCopy方法或者以他们作为方法名开头的方法来给__strong变量赋值,编译器不会插入Retain方法

2 如果是非1所指的方法,或者是把一个变量赋给一个__strong变量,编译器都会插入相应的Retain方法

原文地址:https://www.cnblogs.com/chaoguo1234/p/11147204.html

时间: 2024-11-26 00:26:39

__strong修饰符的相关文章

block 中使用__weak 和__strong修饰符的问题

在ARC环境下,我们常常会使用weak 的修饰符来修饰一个变量,防止其在block中被循环引用,但是有些特殊情况下,我们在block中又使用strong 来修饰这个在block外刚刚用__weak修饰的变量,为什么会有这样奇怪的写法呢? 后来上网查资料,给的解释就是下面的这段话: 在block中调用self会引起循环引用,但是在block中需要对weakSelf进行 strong,保证代码在执行到block中,self不会被释放,当block执行完后, 会自动释放该strongSelf: 对于程

__strong 修饰符

__strong 是id类型和所有对象类型默认的所有权修饰符 __strong 表示对对象的强引用,在ARC中持有强引用变量在超出其作用域或强引用失效(如被置为nil),则引用对象被自动释放 id __strong obj1=[[NSObject alloc] init]; /* create object A */ /* * obj1持有对对象A的强引用 */ id __strong obj2=[[NSObject alloc] init]; /* create object B*/ /* *

__weak 修饰符

就像前面我们看到的一样,__weak 修饰符提供的功能如同魔法一般. 1,若附有__weak 修饰符的变量所引用的对象被废弃,则将nil 赋值给该变量. 2,使用附有__weak 修饰符的变量,即是使用注册到autoreleasepool 中的对象. 1,若附有__weak 修饰符的变量所引用的对象被废弃,则将nil 赋值给该变量. 这些功能像魔法一样,到底发生了什么,我们一无所知.所以下面我们来看看它们的实现. {         id __weak obj1 = obj; } 假设变量obj

OC基础[email protected]后的修饰符及其用法小结

[email protected]后的修饰符 strong : 该属性值对应 __strong 关键字,即该属性所声明的变量将成为对象的持有者,等同于"retain" weak : 该属性对应 __weak 关键字,与 __weak 定义的变量一致,该属性所声明的变量将没有对象的所有权,并且当对象被释放之后,对象将被自动赋值nil,记住IBOutlet应该使用weakcopy : 和之前的copy一样,复制一个对象并创建strong关联assign : 对象不能使用assign,但原始

静态修饰符static,类中的常量定义修饰符

static可以用来区分成员变量.方法是属于类本身还是属于类实例化后的对象.有static修饰的成员属于类本身,没有static修饰的成员属于类的实例. 静态变量仅在局部函数域中存在,但当程序执行离开此作用域时,其值并不丢失static是一个修饰符,用于修饰成员(成员变量和成员函数)静态成员随着类的加载而加载.静态成员优先于对象存在.静态成员被所有对象所共享静态成员多了一个中调用方式,可以被类名直接调用.静态的优缺点优点: 静态成员多了一种调用方式.可以直接被类名调用 格式 :类名.静态成员.也

有趣的修饰符之??、?:、?

良好的程序修养在于灵活运用各类语法(修饰符).本文介绍下,在C#语言中的??(双问号操作符).?:(三元表达式).?(单问好操作符) 1,?? 为了实现Nullable数据类型转换成non-Nullable型数据,就有了一个这样的操作符"??(两个问号)",双问号操作符意思是取所赋值??左边的,如果左边为null,取所赋值??右边的. 比如int y = x ?? -1 如果x为空,那么y的值为-1. 于是这时候就可以把最上面第二段代码改成:string strParam= Reque

修饰符-包-内部类-代码块执行顺序

1.访问权限修饰符     从大到小的顺序为:public--protected--default--private     private--只能在同一类中使用;     default--不用写出来,默认不加.可以被同一包中的类使用     protected--可以被不同包的子类使用     public--可以被不同包的其它类使用 2.各种修饰符的修饰对象(可修饰哪些:类/接口/方法/属性)(多个修饰符连用是可以没有顺序的!)     1)访问权限修饰符:public/default--

访问修饰符

访问修饰符:public.protected.Default.private Public:是公共的,公有的.在任何一个地方都可以访问,一个类里面只有一个public的类,对外的公共类只有一个.成员变量可以用public.局部变量不可使用访问修饰符. Public void getName(){ } Protected:受保护的,在同一个包中可以访问,或者是不同包中的子类可以访问. Protected void getName(){} Default:默认的访问修饰符,只能在同一个包中访问. (

scala学习手记10 - 访问修饰符

scala的访问修饰符有如下几个特性: 如果不指定访问修饰符,scala默认为public: 较之Java,scala对protected的定义更加严格: scala可以对可见性进行细粒度的控制. scala的默认访问修饰符 如果没有修饰符,scala会默认把类.字段.方法的访问修饰符当做public.如果要将之调整为private或protected,只需在前面添加对应的修饰符关键字即可.就如下面的程序: class Microwave{ def start() = println("star