码迷,mamicode.com
首页 > 其他好文 > 详细

Block实现-block存储域

时间:2016-03-24 06:29:33      阅读:192      评论:0      收藏:0      [点我收藏+]

标签:

Block转换为Block的结构体类型的自动变量,_block变量转换为_block变量的结构体类型的自动变量,所谓结构体类型的自动变量,即栈上生成的该结构体的实例。我们已经了解了block时oc对象,该block的类为_NSConcereteStackBlock,虽然该类并没有出现以变换源代码中,还有很多类似的类

_NSConcereteStackBlock    对象存储域在栈上

_NSConcereteGlobalBlock     域全局变量一样,设置在程序的数据区域(.data中)

_NSConcereteMallocBlock   设置在malloc函数分配的内存(堆上)块中。

下面我们介绍一下一个应用程序的内存分配

并非不是所有的block都是NSConcereteStackBlock,但是事实并不是这样的,在记述全局变量的地方使用Block语法时,生成的block为_NSConcereteGlobalBlock类对象。

#import <Foundation/Foundation.h>
void(^blk)(void)=^{printf("Block");};
int main() {
    blk();
    return 0;
}

将上面源代码进行转换之后得到结果:

struct __blk_block_impl_0 {
  struct __block_impl impl;
  struct __blk_block_desc_0* Desc;
  __blk_block_impl_0(void *fp, struct __blk_block_desc_0 *desc, int flags=0) {
    impl.isa = &_NSConcreteGlobalBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

 

我们可以清晰的看到这里的block是全局变量,因为在全局变量的地方不能够使用局部变量,由此可以得知此结构体实例不依赖任何执行时候的状态,所以整个程序只需要一个实例,即使在函数内而不是记述广域变量的地方使用block语法时,之遥block不截获自动变量,就可以将block用结构体设置在程序的数据区域。

在出现一下两种方式的时候,block是_NSConcereteGlobalBlock 类对象

1 记述全局变量的地方使用block语法

2 block语法的表达式中不使用应截获的自动变量的时候。

 

除此之外的block都要配置在栈上。那么现在问题就来了,我们什么时候使用_NSConcereteMallocBlock,总不能不用,这正是为了解决下面两个问题,

1 Block超出变量作用域但是却可存在。

2 _block变量用结构体成员变量_fowarding存在的原因。

我们需要了解,配置在全局变量上的block在变量作用域外也可以安全的访问,但是配置在栈上的,如果其所属的变量作用域结束,该block就被遗弃,所以Blocks提供了将栈上的block复制到堆上,这样即使block语法记述的变量作用域结束,堆上的block还可以继续存在。

_block变量存储域

需要注意的是,将栈上的_block变量用结构体实例在_block变量从栈上复制到堆上的时候,会将成员变量的_forwarding的值替换为复制目标的堆上的_block变量的结构体实例的地址。

Block实现-block存储域

标签:

原文地址:http://www.cnblogs.com/aizhiyuan/p/5313912.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!