Block(二) 的内存管理以及特性

2016-05-22  本文已影响35人  kingandyoga

Block(二) 的内存管理以及特性

一 . Block放在哪里

Block 分为三种类型:

这张图里面很好的解释了三个block在内存里面的分布

alt textalt text

_NSConcreteGlobalBlock

1. 当block 定义在全局作用域的时候,就是global_block
2. 当block 的方法不获取任何外部变量的时候,就是global_block

除此之外,其他形式的block都是stack_block,当然也有例外


在这里还是用代码的形式来学习比较合适。

栈和堆

void foo()
{
    __block int i = 1024;
    int j = 1;
    void (^blk)(void);
    void (^blkInHeap)(void);
    blk = ^{
        printf("%d, %d\n", i, j);
    };
    blkInHeap = CFBridgingRelease((__bridge CFTypeRef _Nullable)(blk));
}



- (void)fooBar
{
    void (^blk)(BOOL);
    BlockTest* t = [[BlockTest alloc]init];
    t.block = blk;
    void (^oblk)(void) = ^{ printf("%d\n", t.block);};
    void (^oblkInHeap)(void) = [oblk copy];//oblkInHeap在堆中
}

对于堆跟栈block的变量,我们可以看下面这个例子。

- (void)tt{
    
    __block int  i = 1024;
    int j = 1;
    void (^block)(void);
    block = ^{
        NSLog(@"%d,%d",i,j);
    };
    block();
    void(^blockInHeap)(void) = [block copy];
    blockInHeap();
    i++;
    j++;
    block();
    blockInHeap();
    
    
}

我在这里解释一下这段代码过程中发生的事情。
在我们定义一个__block int i;之后i就已经在栈上了,之后我们定义j,j还不在栈上。
在我们block = ^{} 的时候他会拷贝没有__block标记变量的内存区,这时候j就在栈上了。

void(^blockInHeap)(void) = [block copy];的时候会拷贝block的内存去到堆上。
在i++ j++之后,由于之前就已经拷贝了一份j的复制品,这时候展示出来的j是在栈上的j,而不是真正的j。而i不同,因为i被记录下来的是地址。

全局block

static int(^maxIntBlock)(int, int) = ^(int a, int b){return a>b?a:b;};

对于全局block里面的变量与block的存储没什么关系,反正是全局变量,大家都访问得到。

二 . 其他特性

对block进行复制:

  1. 对全局的block 调用copy,会返回原指针。(这个很好理解)
  2. 对于栈上block 调用copy,会返回新复制到堆上的block的指针,而且__block变量也会被多拷贝一份。
  3. 对于在heap上的block,调用copy,只会增加他的饮用计数
上一篇 下一篇

猜你喜欢

热点阅读