ARC内存管理机制详解

ARC在OC里面个人感觉又是一个高大上的牛词,在前面Objective-C中的内存管理部分提到了ARC内存管理机制,ARC是Automatic Reference Counting—自动引用计数。有自动引用计数,那么就得有手动引用计数MRC(Mannul Reference Counting),前面已经提到过了MRC。那么在ARC模式下是不是意味着我们就可以一点也不用进行内存管理的呢?并不是这样的,我们还需要代码进行内存的管理。下面会结合着代码把OC中的ARC机制做一个详细的总结(欢迎大家批评指针,转载请注明出处 )。

在ARC机制下是少不了下面这些东西的:

1.关键字 __strong  默认值,表示只要有强引用指针指向该变量,则该变量会一直存在。

2.关键字__weak 弱引用,表示若没有任何强引用指针指向该变量,会自动将变量的值置为空,即nil状态。

3.关键字 __autoreleasing 用于标示自动释放的变量

4.__unsafe_unretained 不安全的弱引用,若没有任何强引用指针指向该变量,不会自动设为空,会成为野指针。

关于Weak和Strong,看下图吧:

第一次接触ARC的小伙伴们看到上面的概念可能会一头雾水,上面说的是个啥?都是哪跟哪?不用着急,下面会有实例代码,结合着实例代码,然后再做一个总结,你就会有种豁然开朗的感觉。你就会明白,哦,原来ARC是这么一回事。好啦,废话少说,用代码讲东西才是王道,代码走起。(为了方便我们观察内存的释放情况,可以设置断点来单步运行)

为了做测试使用,我们建一个测试类,并重写dealloc方法来观察内存的释放情况,测试类如下;

一.__strong:  强引用,是ARC中变量声明的默认值,用大白话讲就是你手动分配的堆内存,如果没有指针指向这块内存,那么这块内存就会被回收

1.当声明变量为强引用时,对象的指针出栈时,如果该指针指向的内存空间没有别的指针指向他,就自动掉用dealloc方法释放堆内存测试代码如下:

代码运行结果:

代码说明:从运行结果来看,出代码块后我们定于的指针变量会随着我们代码块的结束而释放,就没有指针指向我们分配的堆内存了,以为默认为strong,所以在ARC机制下会立即调用dealloc来释放堆内存。

2.给对象指针重写分配内存的情况,代码如下:

代码运行结果:

代码说明:我们先给strong类型的对象指针分配内存空间,然后再次分配内存空间,在第二次分配空间的时候,就没有对象指针指向原有的内存空间,所以在第二次分配空间之后就会把原有的内存空间给释放掉,在出代码块的时候,对象指针也会随着栈内存的释放而释放掉,也没有对象指针指向第二次分配的内存了,所以会被释放掉。

 3.把对象指针置为空时,分配的堆内存会立即被释放掉。相应的代码如下:

代码运行结果:

代码说明:把指向该内存空间的对象指针置空,就相当于没有指针指向该内存空间,所以在strong下会被立即释放。

4.把新的对象指针指向堆内存空间,然后把原有的指针进行置空

代码如下:

运行结果:

代码说明:当两个指针同时指向一块内存空间时,把原有的指针置为空,这块内存空间不会被释放的,因为还有其他的指针指向该内存空间。

二. __weak 归零弱引用:在若指针指向的内存被释放后,若引用的指针则会置零

归零弱引用:弱引用的指针指向强引用的内存时,是不影响其释放内存空间的,当弱引用指针所指空间被释放掉得时候,该弱引用指针会被置零。

代码如下

运行结果如下:

代码说明:当出大括号时强引用指针会被释放掉,之前开辟的堆内存空间只有一个弱引用指针指向他,所以在ARC中会被自动释放,弱引用指针会置零。

三. __autoreleasing 自动释放,一般结合着@autoreleasepool使用。

 1.自动释放修饰的指针所指向的内存空间会在自动释放池结束的时候会被释放,代码如下

代码运行结果:

代码说明:自动释放池结束后,自动对象指针指向的内存空间会被释放,但上面的用法会产生野指针。

2.__autoreleasing结合着自动释放池会延迟内存空间的释放

代码如下:

运行结果:

代码说明:由运行结果可以看出即使把指向内存空间的自动释放类型的指针置空,其对应的内存空间不像强引用那样被直接释放掉,而是等到自动释放池结束后在释放,这就是延迟释放。

3.被自动释放类型的指针用过的内存空间,在自动释放池结束的时候一样会被释放掉。

代码如下:

代码运行结果:

代码说明:上面的代码可能会引起内存泄露,因为如果第一次分配空间的时候如果我们往对象里加入的是一个视频,那么在第二次给自动释放类型的指针分配内存的时候,前面的内存空间不会被释放掉,直到自动释放池结束后两个内存空间才会被释放掉。

四,strong, autoreleasing,weak混在一起的使用情况

在weak中的例子,我们能得到weak和strong同指向一块内存空间,当strong的指针不指向该内存空间时,这块内存空间就可以被释放掉,而weak指针被置零。

内存空间只要有autoreleasing或者strong的指针所持有,就不会被释放

1.strong和autoreleasing的混用

(1).strong类型的指针指向自动释放的空间

代码如下:

运行结果如下:

运行结果说明:上面是先让自动释放类型的指针指向该内存空间,然后再使强类型的指针指向该内存空间,在出自动释放池的时候是不会释放该内存空间的,直到强引用指针被释放掉,才释放该内存空间。

(2).自动释放类型的指针指向strong类型的指针所分配的空间的情况

代码运行结果:

结果说明:当strong修饰的指针随着栈的释放而释放,但其指向的内存空间并没有被释放,因为他还被自动释放类型的指针所持有,所以在出自动释放池的时候才会被释放。

(3).strong 类型的指针会指向自动释放类型的空间内存,当strong指针被置空时该内存不会被释放。

代码如下:

​代码运行结果:

2.弱类型和自动释放类型的混用

代码如下:

代码运行结果:

代码说明:即使有弱引用类型的指针指向该内存空间在出自动释放池的时候,该内存空间也会被释放。弱引用的指针会被置零。

上面写了这么多来点总结性的东西吧:strong 修饰的指针指向的空间如果没有其他指针就会被释放掉(weak类型的不算), 自动释放类型的指针如果没有其他类型的指针指向该内存空间时,当自动释放池结束后就会释放。

上面的总结暂且这么说吧,是根据笔者自己的理解所总结的内容,不免有偏颇之处,欢迎批评指正,转载请注明出处。

打赏支持我写出更多好文章,谢谢!

打赏作者

打赏支持我写出更多好文章,谢谢!

1 2 收藏 评论

关于作者:青玉伏案

乐于分享,广交善缘。走在技术的路上,一直在学习中。(http://www.cnblogs.com/ludashi/)https://github.com/lizeluQQ群:310800319 个人主页 · 我的文章 · 3 ·    

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部