美文网首页
__block能够修改变量的原因

__block能够修改变量的原因

作者: tom555cat | 来源:发表于2017-08-01 00:51 被阅读47次

    为什么不加__block不能修改变量值

    普通变量,数值型或对象型,没有加__block时,Block捕获的是变量,不是变量的地址,因为在函数里对变量做修改不起任何作用,所以编译器层面禁止对捕获的变量进行修改。如果捕获的是变量的地址的话,就可以修改,例如:

    static int num = 10;
    
    bbk blk = ^{
        num++;
    };
    
    NSLog(@"%d", num);
    blk();
    NSLog(@"%d", num);
    
    输出结果:
    10
    11
    

    编译成C++,看看对静态变量num做了什么:

    struct __main_block_impl_0 {
      struct __block_impl impl;
      struct __main_block_desc_0* Desc;
      int *num;
      __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int *_num, int flags=0) : num(_num) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };
    

    可以看到Block捕获的是静态变量的地址"int *num",所以可以根据这个指针对静态变量做修改。

    为什么加了__block就能修改变量值

    使用了__block,可以修改变量值,根本原因还是因为获取到了变量的地址,看一下这段代码:

    int main(int argc, const char * argv[])
    {
        __block int a = 100;
        
        Blk blk_t;
        {
            blk_t = ^(id obj){
                a = 200;
            };
        }
        
        blk_t(@"Hello");
        
        return 0;
    }
    

    编译成C++看一下我们的“a=200”究竟做了什么,

    static void __main_block_func_0(struct __main_block_impl_0 *__cself, id obj) {
      __Block_byref_a_0 *a = __cself->a; // bound by ref
    
                (a->__forwarding->a) = 200;
            }
    

    __forwarding指针是一个指向自己__block实例的指针(当在栈上时),又通过__forwarding指针取到了变量a的地址进行赋值,所以最终是拿到了变量的地址,所以可以对变量进行修改。

    相关文章

      网友评论

          本文标题:__block能够修改变量的原因

          本文链接:https://www.haomeiwen.com/subject/qqpdlxtx.html