__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 *_objc_retain@GOTPCREL(%rip) ##赋值的时候,也会调用Retian方法
总结
对于__strong修饰符,编译器会根据情况插入Retain方法:
1 如果是alloc/init/new/copy/mutableCopy方法或者以他们作为方法名开头的方法来给__strong变量赋值,编译器不会插入Retain方法
2 如果是非1所指的方法,或者是把一个变量赋给一个__strong变量,编译器都会插入相应的Retain方法
分类:
Objective-C
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了