Block存储域

第一、在OC中允许block改写值的变量有三种:

  1. 静态变量
  2. 全局变量
  3. 静态全局变量

code示例如下所示:

int global_val=1;

staticint static_global_val=2;

int main(int argc,const
char * argv[]) {

@autoreleasepool {

static int static_val=3;

void (^blk)(void)=^{

global_val *=2;

static_global_val+=3;

static_val+=4;

NSLog(@"global_val is %d",global_val);

NSLog(@"static_global_val is %d",static_global_val);

NSLog(@"static_val is %d",static_val);

};

blk();

return 0;

}

}

执行结果:

global_val is 2

static_global_val is 5

 static_val is 7

第二、Block存储域

__block说明符严格意义上来说是一种存储域说明符,用来指定该变量的存储位置

在C语言中,static表示存在静态变量区域,auto表示存储在栈中,register表示存在寄存器,__block变量是结构体类型的自动变量

Block是objective-c对象,_NSConcreteStackBlock表示存储为栈,_NSConcreteGlobalBlock表示全局变量区,

_NSConcreteMallocBlock表示存储区域是堆

1、_NSConcreteGlobalBlock实例

当block变量不适用截获的自动变量时,可以采用全局变量,如下所示

typedef void(^TEST)(void);

TEST test;

int main(int argc, const char * argv[]) {

@autoreleasepool {

int val=3;

test=^{

}

test();

return 0;

}

}

2、_NSConcreteStackBlock栈类型block变量最常见

配置在全局变量的block,在变量作用域外通过指针可以安全地访问,但设置在栈上的block,如果其所属的变量作用域结束了,该block就被废弃,

复制到堆上的__block变量在变量作用域结束时不受影响

__block变量用结构体成员变量__forwarding可以实现无论__block变量配置在栈上还是配置在堆上都能够正确访问__block变量第四、

__block变量用结构体成员变量__forwarding实现无论__block变量无论在配置在栈还是配置在堆上,都能够正确访问__block变量

对于_NSConcreteStackBlock变量执行copy,会从栈复制到堆

对于_NSConcreteGlobalBlock变量执行copy,什么也不做

对于_NSConcreteMallocBlock变量执行copy,引用计数增加

copy示例:

blk=[[[[blk copy]copy]copy]copy];

解释为如下

{ /*

*blk复制到堆

*将配置在堆上的block赋值给变量tmp

*变量tmp持有强引用的block

*/

blk_t tmp=[blk copy];

/**

* blk和tmp强引用block

*/

blk=tmp;

}

跳出作用域,tmp执行release释放,blk只有block没有被释放,以此循环。

结论:不管block配置在何处,用copy方法复制都不会引起任何问题,在不确定时用copy方法即可

时间: 2024-10-15 05:11:55

Block存储域的相关文章

Block实现-block存储域

Block转换为Block的结构体类型的自动变量,_block变量转换为_block变量的结构体类型的自动变量,所谓结构体类型的自动变量,即栈上生成的该结构体的实例.我们已经了解了block时oc对象,该block的类为_NSConcereteStackBlock,虽然该类并没有出现以变换源代码中,还有很多类似的类 _NSConcereteStackBlock    对象存储域在栈上 _NSConcereteGlobalBlock     域全局变量一样,设置在程序的数据区域(.data中) _

Block存储域探析

接<Block截获自动变量实现与__block修饰符内部实现>我们继续探讨Block 留下的问题 1,__Block_byref_i_0 *__forwarding;这个指向自身的指针是什么鬼,有什么作用,什么时候用? 2,Desc_0结构体中多出来的void (*copy) void (*dispose)这两个方法有什么作用,什么时候用? Block 和 __block变量的实质 名称 实质 Block 栈上Block的结构体实例 __block变量 栈上__block变量的结构体实例 Bl

block存储区域——如何验证block在栈上,还是堆上

block存储区域 这就需要引入三个名词: ● _NSConcretStackBlock ● _NSConcretGlobalBlock ● _NSConcretMallocBlock 正如它们名字说的那样,说明了block的三种存储方式:栈.全局.堆. [要点1]定义在函数外面的block是global的:另外如果函数内部的block,但是没有捕获任何自动变量,那么它也是全局的.比如下面这样的代码: typedef int (^blk_t)(int); for(...){ blk_t blk

js读写Cookie问题(Cookie存储时长、Cookie存储域)汇总

在采集网站用户行为数据/使用js对用户行为做交互时,经常会使用到Cookie,了解Js Cookie的读写,以及一些细节,非常重要.   什么是Cookie 所谓Cookie,只是一条极为短小的信息,它被浏览器自动地放置在访问用户的电脑硬盘中. 例如:C:\Users\[user]\AppData\Roaming\Microsoft\Windows\Cookies 如上图所示,打开的一个文件里面,标示了一个域下多个Cookie的信息. 检测/判断浏览器是否支持Cookie 在绝大多数浏览器中,可

Block存储区域

Block存储区域 首先,需要引入三个名词: ● _NSConcretStackBlock ● _NSConcretGlobalBlock ● _NSConcretMallocBlock 正如它们名字显示得一样,表明了block的三种存储方式:栈.全局.堆.block对象中的isa的值就是上面其中一个,下面开始说明哪种block存储在栈.堆.全局. ------------[要点1]:全局block------------ ● 定义在函数外面的block是global类型的 ● 定义在函数内部的

Lucene——Field.Store(存储域选项)及Field.Index(索引选项)

Field.Store.YES或者NO(存储域选项) 设置为YES表示或把这个域中的内容完全存储到文件中,方便进行文本的还原 设置为NO表示把这个域的内容不存储到文件中,但是可以被索引,此时内容无法完全还原(doc.get) Field.Index(索引选项) Index.ANALYZED:进行分词和索引,适用于标题.内容等 Index.NOT_ANALYZED:进行索引,但是不进行分词,如果身份证号.姓名.ID等,适用于精确搜索 Index.ANALYZED_NOT_NORMS:进行分词但是不

OC 中的block存储位置

一.block块的存储位置(block块入口地址):可能存放在2个地方:代码区.堆区(程序分5个区,还有常量区.全局区和栈区). 详细介绍: 情况1:代码区 不访问处于栈区的变量(例如局部变量),且不访问处于堆区的变量(例如alloc创建的对象).也就是说访问全局变量也可以. /** 没有访问任何变量 */ int main(int argc, char * argv[]) { void (^block)(void) = ^{ NSLog(@"==="); }; block(); }

RHEV:如何配置(增加)NFS格式存储域?

扫描系统逻辑盘: [[email protected] /]# lvscan 设置磁盘为可用状态: 创建目录: 编辑exports文件: 启动NFS服务: 启动exportfs服务 在防火墙中增加NFS服务:关闭防火墙,启动服务: 在管理后台增加存储卷: 附加到数据中心: 当状态至维护状态时,激活数据中心: 当颜色变为绿色时候,可用,存储配置完成.

Block源码解析和深入理解

Block源码解析和深入理解 Block的本质 Block是"带有自动变量值的匿名函数". 我们通过Clang(LLVM编译器)来将OC的代码转换成C++源码的形式,通过如下命令: clang -rewrite-objc 源代码文件名 下面,我们要转换的Block语法 1 2 3 4 5 6 7 int main(int argc, const char * argv[]) { void (^blk)(void) = ^{ printf("Block\n"); };