三.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...