文档章节

__block的作用和功能

余成海
 余成海
发布于 2016/08/30 10:36
字数 679
阅读 56
收藏 0

哈,好久没写博客了,oschina的编辑器变漂亮啦!!!!!

int val = 0;
void (^blk)(void) =  ^{
    ++val;
};

先看代码,代码这么写的话会编译失败,提示错误:

原因在于,栈上的局部变量无法在block中编辑,block只做了只读拷贝,解决的办法当然是__block修饰啦,但是__block到底有什么作用,编译器遇到__block做了什么处理,这也是面试中常问的问题。

插个问题,考下大家,看看下面的代码输出的结果是什么.大家可以试下

int val = 0;
void (^blkk)(void) =  ^{
    NSLog(@"~~~~~~~%d", val);
};
val++;
blkk();

----------------------------凌乱分割线--------------------------------

上面的结果当然是0,因为在val++之前,block已经对val做了只读拷贝,所以后来修改val和block中的val无关了,再看下下面的代码

__block int val = 0;
void (^blkk)(void) =  ^{
    NSLog(@"~~~~~~~%d", val);
};
val++;
blkk();

结果就变成1了,所以可以看出__block的作用,__block修饰的变量在block中使用时,block不会对变量只读拷贝操作。

简单说,__block说明符类似static、auto、register一样,作用是改变变量的存储区域,它会使得修饰的变量结构化到block的自动变量中去,解释下这句话,就是说val会被存储到block结构中去。看看编译结果就很清楚了

__block int val = 0;
void ^(blk)(void) = ^(val = 1);

上面这段代码通过编译器编译后出来的结果是这样的:

struct __Block_byref_val_0 {
    void *__isa;
    __Block_byref_val_0 *__forwarding;
    int __flags;
    int __size;
    int val;
};

struct __main_block_impl_0 {
    struct __block_impl  impl;
    struct __main_block_desc_0 *Desc;
    __Block_byref_val_0 *val;

    __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_val_0 *_val, int flags=0) : val(_val->__forwarding) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
    }
}

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
    __Block_byref_val_0 *val = __cself->val;
    (val->__forwarding->val) == 1;
}

........

int main()
{
    __Block_byref_val_0 val = {
        0,
        &val,
        0,
        sizeof(__Blcok_byref_val_0),
        0
    };

    blk = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, &val, 0x2200000);

    return 0;
}

c的代码也是比较好看懂的,可以看到,int val 变成一个结构体了__Block_byref_val_0,在block的结构体中还包含了val。

 

当然大家会想到一个问题,如果有多个block会出现什么情况,同时用到val。会不会出现两个block中的val不一样呢,我们看下代码

__block int val = 0;
void (^blk0)(void) = ^{val = 1};
void (^blk1)(void) = ^{val = 2};

看下转换后的代码:

__Block_byref_val_0 val = {0, 
&val,
0,
sizeof(__block_byref_val_0, 
0)
};

blk0 = &__main_block_impl_0(__main_block,func_0, &__main_block_desc_0_DATA, &val, 0x22000000);
blk1 = &__main_block_impl_1(__main_block,func_0, &__main_block_desc_0_DATA, &val, 0x22000000);

可以看到block赋值了val结构的地址,所以两个block,拥有的是同一块val的数据。这也是编译器把val的结构体定义单独提出来,而不是放到block结构中定义的原因

© 著作权归作者所有

共有 人打赏支持
余成海
粉丝 61
博文 57
码字总数 29577
作品 0
杭州
iOS工程师
OC中的block基础知识

// 1.函数指针专门用来指向C语言的函数的指针(专门用来存储函数名的地址) // 2.选择器是用来存储OC中方法,(存的也是方法名) // 3.block也是专门用来存储方法 (存的是函数体-实现函数功...

鹿微微鹿
2016/03/29
14
0
OC block的第二个作用:协议代理

YTStaff.h #import <Foundation/Foundation.h> //拥有某种能力的对象 @interface YTStaff : NSObject //需要一个block属性 //问:block为什么要使用copy? //答:因为block变量默认是存储在栈...

鹿微微鹿
2016/03/29
21
0
OC中block的作用

Math.h #import <Foundation/Foundation.h> @interface Math : NSObject{ // NSString * _name; } @property(nonatomic, copy) NSString * name; //_name //按给定的方式去计算两个整型数据的......

鹿微微鹿
2016/03/29
96
0
Objective-C中 Block 在iOS在4.0版本的使用

Objective-C中 Block 在iOS在4.0版本的使用 了解何谓block。 了解block的使用方法。 Block 是iOS在4.0版本之后新增的程序语法. 在iOS SDK 4.0之后,Block几乎出现在所有新版的API之中,换句话...

浩浩老师
2015/09/11
228
0
Oracle Internal Event:10200 Consistent Read诊断事件

10200(consistent read buffer status)内部诊断事件可以用于探测一致性读CR(consistent read)块的访问情况,虽然cr读的统计信息可以从v$sysstat或AWR/statspack中获取,但是10200 event还是我...

科技小能手
2017/11/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

原型模式

1、原型模式-定义 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象 克隆(浅度克隆->拷贝值类型或者引用,深度克隆->创建新的对象,开辟新的内存) 例如客户端知道抽象Pro...

阿元
48分钟前
5
0
awk命令扩展使用操作

awk 中使用外部shell变量 示例1 [root@centos01 t1022]# A=888[root@centos01 t1022]# echo "" | awk -v GET_A=$A '{print GET_A}'888[root@centos01 t1022]# echo "aaaaaaaaaaaaa" | aw......

野雪球
今天
10
0
深入解析MySQL视图VIEW

Q:什么是视图?视图是干什么用的? A:视图(view)是一种虚拟存在的表,是一个逻辑表,本身并不包含数据。作为一个select语句保存在数据字典中的。   通过视图,可以展现基表的部分数据;...

IT--小哥
今天
13
0
虚拟机学习之二:垃圾收集器和内存分配策略

1.对象是否可回收 1.1引用计数算法 引用计数算法:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时候计数器值为0的对象就是不可能...

贾峰uk
今天
10
0
smart-doc功能使用介绍

smart-doc从8月份底开始开源发布到目前为止已经迭代了几个版本。在这里非常感谢那些敢于用smart-doc去做尝试并积极提出建议的社区用户。因此决定在本博客中重要说明下smart-doc的功能,包括使...

上官胡闹
昨天
19
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部