zoukankan      html  css  js  c++  java
  • 格而知之16:我所理解的Block(3)

    23、在前文中的例子中,Block结构体里的isa指针还没有详细讲解,这个指针都被置向了_NSConcreteStackBlock,它标识了Block的类型。

    其实除了_NSConcreteStackBlock这个类型外,Block还有其他的类型,这些类型总共有3种:

    (1)、_NSConcreteStackBlock

    (2)、_NSConcreteMallocBlock     

    (3)、_NSConcreteGlobalBlock

    24、这3种类型分别表示了Block对象存储的区域,如下图:

    25、编译器的模式也会影响到Block对象的存储,同一个Block对象在ARC模式下和在MRC模式下可能会存储在不同的区域。接下来,就使用代码来研究一下在ARC模式下和在MRC模式下,全局Block、普通Block、截获变量的Block和截获可变变量的Block分别是怎么存储的。

    26、可以通过打印出Block对象来确定它存储的位置,这3种类型的Block对象打印出来的类分别是:

    (1)、__NSStackBlock__

    (2)、__NSMallocBlock__

    (3)、__NSGlobalBlock__

    普通全局Block

    27、首先在ARC模式下,编写一个全局普通Block,并分别打印出持有这个Block对象的变量,和这个变量的复制值:

    可以发现,两种情况下打印出来的Block对象都是__NSGlobalBlock__类的,说明它们都存储在.data区。

    28、试一下在MRC模式下执行相同的代码:

    发现效果相同。说明,普通全局Block在ARC模式下和MRC模式下的存储区域是一样的,都是.data区。

    截获变量的全局Block

    29、全局Block能截获的变量,只能是全局变量(不可能获取到局部变量)。而全局变量在Block中本身就是可变的了,所以“截获变量的全局Block”就相当于“截获可变全局变量的全局Block”。

    30、编写以下代码,在ARC模式下执行:

    在MRC模式下也执行相同代码:

    从执行结果可以看出,截获了变量的全局Block存储区域和普通全局Block是一样的。这说明了,全局Block都是__NSGlobalBlock__类的,存储在.data区。

    普通Block

    31、对于普通Block,编写以下代码来查看它的存储区域,在ARC模式下分别打印出持有普通Block的变量、持有普通Block的变量的复制值、普通Block对象和普通Block对象的复制值:

    再在MRC模式下也执行相同代码:

    从打印结果可以看出:不论是在ARC模式下还是在MRC模式下,不截获变量的普通Block都是当作__NSGlobalBlock__类对象处理的,存储在.data区。

    还有一点需要注意:前文在使用clang命令转换普通Block的时候,Block对象的isa指针是指向_NSConcreteStackBlock的,说明普通Block本质上是__NSStackBlock__类的;而在此处通过打印可知,因为没有截获变量,编译器实际上就将普通Block当做__NSGlobalBlock__类来处理了。

    截获变量的Block

    32、上文演示的几种Block在不同编译器模式下存储区域并没有差别,接下来的Block就开始有差别了。

    编写以下代码,在ARC模式下分别打印出持有截获变量Block的变量、持有截获变量Block的变量的复制值、截获变量的Block对象和截获变量的Block对象的复制值:

    然后在MRC模式下执行相同代码,查看结果:

    比较两种模式下的打印结果,可以发现:

    (1)、在MRC模式下,截获变量的Block对象本身是存储在栈上的,即使通过持有这个Block对象的变量来访问它,仍然能顺利访问到存储在栈上的Block对象。只有主动调用copy方法,才能将Block对象从栈上复制到堆上;

    (2)、在ARC模式下,截获变量的Block对象本身也是存储在栈上的,只是当使用持有这个Block对象的变量来访问它时,这个Block对象就会被从栈上复制到堆上,这样变量访问到的就是存储在堆上的Block对象了。如果主动调用copy方法,Block对象也会被赋值在堆上;

    (3)、比较两种模式下的区别,可以发现在使用变量访问Block对象的情况下,在不同编译器模式下Block对象的存储区域是不同的。所以才会有ARC模式下没有_NSConcreteStackBlock这种说法。

    截获可变变量的Block

    33、再来看一看最后一种Block,编写以下代码,在ARC模式下分别打印出持有截获可变变量Block的变量、持有截获可变变量Block的变量的复制值、截获可变变量的Block对象和截获可变变量的Block对象的复制值:

    然后在MRC模式下执行相同代码,查看结果:

    可以发现,情况和截获变量的Block一样,都是在使用变量访问Block对象的情况下,在不同编译器模式下Block对象的存储区域不同。那么可以得出以下结论:

    (1)、在不同编译器模式下,截获变量的Block本身都是存储在栈上的;

    (2)、使用变量访问这种Block时,MRC模式下能访问到栈上的对象,ARC模式下访问到的是被复制到堆上的对象。

  • 相关阅读:
    bzoj1015星球大战(并查集+离线)
    bzoj1085骑士精神(搜索)
    bzoj1051受欢迎的牛(Tarjan)
    左偏树学习
    hdu1512 Monkey King(并查集,左偏堆)
    左偏树(模板)
    PAT (Basic Level) Practice (中文) 1079 延迟的回文数 (20分) (大数加法)
    PAT (Basic Level) Practice (中文) 1078 字符串压缩与解压 (20分) (字符转数字——栈存放)
    PAT (Basic Level) Practice (中文) 1077 互评成绩计算 (20分) (四舍五入保留整数)
    PAT (Basic Level) Practice (中文) 1076 Wifi密码 (15分)
  • 原文地址:https://www.cnblogs.com/shayneyeorg/p/5876398.html
Copyright © 2011-2022 走看看