美文网首页
block的源码解读之变量捕获机制(capture)

block的源码解读之变量捕获机制(capture)

作者: GDCoder | 来源:发表于2021-03-19 17:55 被阅读0次

我们在面试的时候经常被问到block,而且也是iOS的特别常见的面试题.比如:

1.block的原理是怎么样的?本质是什么?

2._block的作用是什么?有什么使用注意点?

3.block的修饰词为什么是copy?使用block有哪些使用注意?

4.block在修改NSMutableArray,需不需要添加_block?

接下来带你轻轻松松解读源码,先了解block的本质,我们先创建一个最简单的block如下;

这一个简单的block,我们先用终端把main.m这个文件转成c++代码,我们知道,oc的底层就是c++和c,所以我们利用终端执行下面的操作,把main.m转成c++来看看如下:

接下来我们把main.cpp文件拉到项目开始查看,看一下源码到底是怎么实现的block,打开这个cpp文件,因为main是最后执行的,所以我们直接划到文件的最下面查看如下:

上面的截图一看就是我们刚刚写的那段代码,我们知道变量前面加()一般是强制转换,所以我们可以把上面绿色框框的去掉,看得就比较清晰,剩余如上,最上面的一看就比较简单_main_block_impl_0这个就是创建block的,里面传了2个参数,分别是__main_block_func_0和_main_block_desc这两个东西,而调用block直接就是-->funPtr很大可能就是指针调用,

接下来我们再细看:

这里应该是很容易可以看出它的调用过程了,而上面的1,那个结构体是C++的函数,里面和外面的函数一样,是构造函数,它返回的是结构体本身!

这就是一个很简单的block的调用底层!我们知道block没有这么简单,接下来我们看一个稍微复杂

难度小升级:增加参数如下

然后直接用上面的方法,把这个文件再转成c++文件,结果如下

这个也很清楚,也比较简单,接下来我们难度再升级一点点

难度再小升级:设置一个变量,里面访问,再修改变量,代码如下

这种情况,再没公布结果之前,可能有的同学认为,这个结果是30,也有些人知道是10,但是具体10是怎么来的,我们接下来继续探究,还是生成c++代码看一下

图1

由上面的2张图,我们知道,在执行height=30的时候,block里面的height = 10的,这时候赋值30并没有改变block存储的值是10吧?这里是非常明显,所以我们调用block输出的是hello, World:10,结果非常明显,这就涉及到我们有时候面试官说的,你知道block的变量捕获机制吗(capture).

block变量捕获机制(capture)

首先我们先看一张图

我们上面的例子说的是局部变量,其实我们写的int height = 10;其实是auto int height = 10都有这个就省略没写,auto定义的范围就是我们的大括号,我们知道,刚刚说的就是auto的情况就行了,而且auto是值传递.(auto:叫做自动变量,离开作用域就自动销毁)

block捕获:就是block内部会新增一个变量,存储变量的值,这个就叫做捕获.

接下来介绍static情况,请看下图:

static 定义的是指针传递,它的结果是30,和auto修饰的完全不一样,这是怎么回事呢?还是看一下源码解读

先不说源码,我们是不是可以得出一个结论,auto和static修饰的局部变量都是可以被block捕获吧!这个很清楚.而age传递是啥是&age,是传递的age的指针地址啊,赋值什么都是取的是指针地址,我们再看一下取值是啥:

取得也是地址吧!这个就非常清楚,为什么会出现上面的结果!

思考:为什么auto变量不能也设置传递地址呢?

大家可能有这个疑问,接下来,我就写一个例子来说明一下这个情况:

上面的图就解释了这个问题.

而全局变量是直接不捕获,这个大家可以自己证明,按照我上面的方法,应该是非常清晰

到这里,我相信大家对block的变量捕获应该有一个比较本质的认识了!

大家只要知道这个变量是局部的,还是全局的就知道它能不能捕获!

思考:

下面给大家留一个考题,下面的这2种情况block会不会捕获:

test和test1变量会不会捕获???

接下来博客我会介绍block的类型.来继续探讨block

如果觉得我写得对您有所帮助,请关注我,我会持续更新😄

相关文章

网友评论

      本文标题:block的源码解读之变量捕获机制(capture)

      本文链接:https://www.haomeiwen.com/subject/vxtvcltx.html