__block能夠修改變量的原因

為什么不加__block不能修改變量值

普通變量,數(shù)值型或?qū)ο笮?,沒有加__block時(shí),Block捕獲的是變量,不是變量的地址,因?yàn)樵诤瘮?shù)里對(duì)變量做修改不起任何作用,所以編譯器層面禁止對(duì)捕獲的變量進(jìn)行修改。如果捕獲的是變量的地址的話,就可以修改,例如:

static int num = 10;

bbk blk = ^{
    num++;
};

NSLog(@"%d", num);
blk();
NSLog(@"%d", num);

輸出結(jié)果:
10
11

編譯成C++,看看對(duì)靜態(tài)變量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捕獲的是靜態(tài)變量的地址"int *num",所以可以根據(jù)這個(gè)指針對(duì)靜態(tài)變量做修改。

為什么加了__block就能修改變量值

使用了__block,可以修改變量值,根本原因還是因?yàn)楂@取到了變量的地址,看一下這段代碼:

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指針是一個(gè)指向自己__block實(shí)例的指針(當(dāng)在棧上時(shí)),又通過__forwarding指針取到了變量a的地址進(jìn)行賦值,所以最終是拿到了變量的地址,所以可以對(duì)變量進(jìn)行修改。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容