首先,在了解block三大类型以前,咱们须要了解一个知识:c++
(舒适提醒:若是个人以前博客你没有看,有些概念你不清楚的话,你可能很难理解,若是前面你都看了,这篇博客你看就像切菜同样简单!)程序员
一个由C/C++编译的程序占用的内存分为如下几个部分markdown
栈(stack):由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操做方式相似于数据结构中的栈。数据结构
堆(heap): 通常由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式相似于链表。iphone
全局区(静态区static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另外一块区域,程序结束后由系统释放。函数
文字常量区:常量字符串放在这里, 程序结束后由系统释放测试
程序代码区:存放函数体的二进制代码。spa
相信你们对上面的这些内存分配的知识点都已经很是清楚,那咱们就看一下指针
接下来咱们就看看,block就是一个oc对象,那咱们就能够按照oc的,直接调用class就知道它的类型了code
这里能够看出我前面说的,block就是oc对象,而这个NSGlobalBlock是继承NSBlock的,其余的种类都是继承NSBlock,等说完了,你们能够用这个方法试试其它2种block的的父类.
上面就是block的总共的三种类型:NSGlobalBlock、NSStackBlock、NSMallcBlock,
,这是运行时输出的结果,其实编译的结果可能有点不同,那咱们就把这份文件转成c++文件,这个我以前的博客都提了不少次,此次我就不细说了(xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp)
其实你会发现,编译之后生成的都是NSConcreteStackBlock类型,首先咱们确定以运行时为准,由于编译过程还有个运行,运行就会用runtime动态修改你的东西;还有其实用clang转成c++的代码,有时候并不必定就是最终的代码,其实差异是不大,其实在llvm大概6.0之前都是同样的,如今会生成一个中间文件,还有就是程序运行中也是比较准确,若是有同窗查看源码感受不同,不要很惊讶,这个很正常,能够参考,差异不大.
咱们继续看
而GlobalBlock是在数据区域,MallocBlock是在堆区,StackBlock是在栈区,我这里不说堆、栈、数据区域的区别了,你们这个知识点若是不懂能够去查阅一下它们的区别,否则后面的很难理解
先看个人总结,咱们再细细看
auto变量你们清楚吧?auto变量就是它所在的区域执行完毕,自动销毁的变量.若是不知道请看我上一篇博客,介绍的很是清晰.接下来咱们就一个一个看每种类型的block
请看下面的代码
访问static的局部变量,全局变量a,都不是auto变量,因此上面3种状况都是GlobalBlock,由于GlobalBlock咱们实际中用的很是少,因此这个也没有过多的须要阐述的
按照咱们表格上面说的访问了auto变量的block就是StackBlock,那我看一下下面的代码:
ARC下运行的结果
应该有同窗注意,结果和咱们上面的结论不同,实际上是由于这环境是ARC,ARC下其实帮你作了不少事(这个为何会这样,这个内容仍是有点多,后面的博客,我会细说,你先无论这个为何是这样),因此咱们改为MRC才能看到它的本质(直接把Objective-C Automatic Reference Counting 设置为NO便可),咱们再看下面
MRC下运行的结果
这就是StackBlock类型,下面咱们再深刻看一下这个StackBlock一个特殊状况,以下图
MRC下运行的结果
注意到没有,这个age的值变得很奇怪.这是由于:test()函数的做用域执行结束之后,它的做用域中的栈上面的变量就会销毁,好比里面的block就是StackBlock,全部test()执行完毕之后,block已经被释放了,致使访问内部就会出现混乱的状况.整个block内存被释放了里面的全部都会出现混乱
答案很明显,咱们把block栈内存变成堆内存就好了哇!怎么变成堆block,是否是直接栈调用copy就能是堆block了,那咱们再试试:
是否是就很容易解决了!可能有同窗还有疑问,若是把GlobalBlock也来调用copy会是怎么样呢?这个你们能够本身验证,答案仍是:GlobalBlock,若是把MallocBlock也来调用copy会是怎么样呢?这个你们能够本身验证,答案仍是:引用计数加1
还有若是咱们block访问一个对象,一个对象也是auto变量,因此也是同样的,这些我就不验证了,若有疑问能够评论区讨论.
这个上面已经说的很清楚了
相信还有同窗有疑问,刚刚咱们是MRC下测试的,至于ARC为何会是另外一个结果,我后面的博客会说到!