IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Objective-C中MRC和ARC的自我理解 -> 正文阅读

[移动开发]Objective-C中MRC和ARC的自我理解

MRC: 手动引用计数。

?

alloc -- 分配一个对象的内存空间

retain --使一个对象的引用计数加1

release --使一个对象的引用计数减1

retainCount --获取当前对象的引用计数值

aotorelese --调用对象的aotorelease方法的话,将对象的内存管理放到aotorelease poll中,当aotorelease poll结束的时候自动调用release操作,使引用计数减1

dealloc 在MRC中调用dealloc,需要显示的调用 super dealloc方法,废弃父类的方法。

在MRC模式下必须遵循谁创建,谁释放,谁引用,谁管理

ARC : 自动引用计数

ARC是编译器(LLVM)在对应的位置自动插入retain和release操作之外,还需要Runtime的功能支持,是LLVM和Runtime协作的结果。ARC中禁止手动调用retain、release、retainCount、dealloc.

ARC中新增了weak、strong属性关键字。

MRC和ARC的区别:

1、MRC是手动管理内存,ARC是自动管理内存,由编译器和Runtime进行协作。

2、ARC中禁止调用retain、release、autorelease、retainCount、dealloc操作

在MRC下使用ARC,使用?-fobjc-arc修饰文件,启用ARC

在ARC下使用MRC,使用?-fno-objc-arc修饰文件,禁止ARC

strong和weak

strong强引用,执行了retain操作,weak弱引用,表示该属性是一种非拥有关系,没有执行retain操作。

weak属性在设置新值时既不保留新值也不会释放旧值,类似于assign;当对象被释放时,属性也会被清空。这样可以有效地防止崩溃(因为OC中给没有对象地址的指针发送消息,不会崩溃;但是给有内存地址但地址中是空对象的指针,即野指针,发送消息会崩溃)。

对于weak对象会放入一个hash表中,用weak指向的对象内存地址作为key,当此对象的引用计数值为0时会调用dealloc,使用key在hash表中搜索,将找到的所有对象置为nil。

Runtime如何实现weak变量的自动置nil?

引用计数管理

alloc的实现:

经过一些列函数的封装调用,最终调用了c函数calloc。

此时并没有设置引用计数值为1,但是我们通过retainCount获取到的引用计数值为1。这是什么原因呢?

retain的实现:

// 通过当前对象的指针,经过hash函数的运算,可以快速的在sidetables找到它对应的sidetable
SideTable& table = SideTables()[this];

// 在sidetable中去获取引用计数map这样的一个成员变量,然后通过当前对象的指针,在sidetable的引用计数表中去获取当前对象的引用计数值。
size_t& refcntStorage = table.refcnts[this];

// 对引用计数值进行加1操作,size_t 是unsign long 型的,第一位是weakly_referenced第二位是deallocating 所以这里加的值不是实际的1,而是一个宏定义 SIZE_TABLE_RC_ONE,加的一个偏移量
refcntStorage += SIDE_TABLE_RC_ONE;

// 这两次都是hash查找,也就是说在进行retain操作时经历了两次hash查找。

思考一下:我们在进行retain操作时,系统是如何查找它对应的引用计数的?

解析:通过两次hash查找,来找到它对应的引用计数值,然后进行加一操作。这里的两次查找,第一次是找到对应的sidetable表,第二次是从表的引用计数表中获取当前对象的引用计数值。

release的实现:

SideTable& table = SideTables()[this];

//根据当前对象指针访问table的引用计数表,查到它当前对应的引用计数表。
RefcountMap::iterator it = table.refcnts.find(this);

//把查找到的值进行减一操作
it ->second -= SIDE_TABLE_RC_ONE;

retainCount实现:

SideTable& table = SideTables()[this];

// 声明一个局部变量,初始值为1
size_t refcnt_result = 1;

// 通过当前对象拿到引用计数表中去查找
RefcountMap :: iterator it = table.refcnts.find(this);

// 对结果做一个向右偏移的操作,然后再结合局部变量的1进行加的操作
refcnt_result += it ->second >> SIDE_TABLE_RC_SHIFT;

这也就解释了,alloc出来的对象,我们虽然没有设置引用计数值为1,但是我们通过retainCount去获取到的引用计数值为1的原因。

dealloc的实现:

从下面流程图来讲述dealloc的实现原理:首先会先调用一个私有函数_objc_rootDealloc(),这个私有函数会调用一个rootDealloc()函数,在这个函数内部判断当前对象是否可以释放;直接释放的一个判断条件是【1、判断当前对象是否使用了非指针型isa(NONPOINTER_ISA); 2、当前对象是否有weak指针指向它,weakly_referenced; 3、当前对象是否有关联对象 has_assoc; 4、当前对象是否涉及了C++相关的代码 has_cxx_dtor以及当前对象是否使用ARC来管理内存; 5、当前对象的引用计数是否通过sidetable的引用计数表来维护的has_sidetable_rc。】如果上述5个条件有任一个满足,那就不能直接释放,需要调用object_dispose()对象清除函数。如果上述5个条件,都不满足,那就可以直接调用C函数free()直接释放。

object_dispose()函数的实现

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-03-03 16:26:11  更:2022-03-03 16:28:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 16:27:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码