Block中 block實現原理

2021-09-07 14:39:36 字數 2182 閱讀 9763

三.block中__block實現原理

我們繼續研究一下__block實現原理。

1.普通非物件的變數

先來看看普通變數的情況。

#import int main(int argc, const char * ar**) ; myblock(); return 0; }

把上述**用clang轉換成原始碼。

struct __block_byref_i_0 ;

struct __main_block_impl_0

};static void __main_block_func_0(struct __main_block_impl_0 *__cself)

static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src)

static void __main_block_dispose_0(struct __main_block_impl_0*src)

static struct __main_block_desc_0 __main_block_desc_0_data = ;

int main(int argc, const char * ar**) ;

void (*myblock)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_data, (__block_byref_i_0 *)&i, 570425344));

((void (*)(__block_impl *))((__block_impl *)myblock)->funcptr)((__block_impl *)myblock);

return 0;

}

從原始碼我們能發現,帶有 __block的變數也被轉化成了乙個結構體__block_byref_i_0,這個結構體有5個成員變數。第乙個是isa指標,第二個是指向自身型別的__forwarding指標,第三個是乙個標記flag,第四個是它的大小,第五個是變數值,名字和變數名同名。

__attribute__((__blocks__(byref))) __block_byref_i_0 i = ;

原始碼中是這樣初始化的。__forwarding指標初始化傳遞的是自己的位址。然而這裡__forwarding指標真的永遠指向自己麼?我們來做乙個實驗。

//以下**在mrc中執行

__block int i = 0;

nslog(@"%p",&i); void (^myblock)(void) = [^copy];

我們把block拷貝到了堆上,這個時候列印出來的2個i變數的位址就不同了。

0x7fff5fbff818

<__nsmallocblock__:>

這是block 裡面 0x1002038a8

位址不同就可以很明顯的說明__forwarding指標並沒有指向之前的自己了。那__forwarding指標現在指向到**了呢?

block裡面的__block的位址和block的位址就相差1052。我們可以很大膽的猜想,__block現在也在堆上了。

出現這個不同的原因在於這裡把block拷貝到了堆上。

由第二章裡面詳細分析的,堆上的block會持有物件。我們把block通過copy到了堆上,堆上也會重新複製乙份block,並且該block也會繼續持有該__block。當block釋放的時候,__block沒有被任何物件引用,也會被釋放銷毀。

__forwarding指標這裡的作用就是針對堆的block,把原來__forwarding指標指向自己,換成指向_nsconcretemallocblock上覆制之後的__block自己。然後堆上的變數的__forwarding再指向自己。這樣不管__block怎麼複製到堆上,還是在棧上,都可以通過(i->__forwarding->i)來訪問到變數值。

所以在__main_block_func_0函式裡面就是寫的(i->__forwarding->i)。

Block實現原理

import int main int argc,const char argv i 3 myblock return 0 執行結果 i的值是 2為什麼是2 不是3呢?帶著這個疑問我們往下看 編譯main.m檔案,1.開啟終端,2.找到工程檔案,3.找到main.m檔案所在的位置,4.clang r...

block的實現原理

main.m import block實際上是 指向結構體的指標 編譯器會將block的內部 生成對應的函式 void test1 block func 0 void test1 a 20 block 10 void test2 a 20 block 20 void test3 a 20 block...

block實現原理詳解

對於大多數人來講,block內部到底是怎樣實現的呢?我們可以借助clang將其編譯成為c 的 就可以看出,block到底是什麼東西,先來看這樣乙個問題,int age 10 void block age 30 block 10 以及下面的這一段 block int age 10 void block...