block実装原理の詳細

4159 ワード

Arc下block使用時、外部変数参照時、変数が__使用されている場合block修飾と未使用修飾は違いますが、どのような違いがありますか??次はこの問題を詳しく説明します.
多くの人にとって、block内部はどのように実現されているのでしょうか.clangを用いてc++のコードにコンパイルすることで、blockが何なのかを見ることができます.
まずこのような問題を見てみましょう
<!-- lang: cpp --> int age = 10; void (^block)() = ^{ NSLog(@"%d",age); }; age = 30; block();//10 

次のコード
<!-- lang: cpp --> __block int age = 10; void (^block)() = ^{ NSLog(@"%d",age); }; age = 30; block();//30 

この2つの結果は異なり、最初の出力は10、2番目の出力は30です.
この中で何をしたのか知りたい!C++コードにコンパイルする必要があります.何をしたのか見てみましょう.端末を使用して、mianに移動します.mファイルでは、次のコードclang-rewrite-objc mainを使用する.mこれをコンパイルmainを生成する.cppファイルを開くとmianを開きます.cppはファイルの一番下のmain関数で
<!-- lang: cpp -->
int main(int argc, const char * argv[])

{
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 

    __attribute__((__blocks__(byref))) __Block_byref_age_0 age = {(void*)0,(__Block_byref_age_0 *)&age, 0, sizeof(__Block_byref_age_0), 10};
    void (*block)() = (void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_age_0 *)&age, 570425344);
    (age.__forwarding->age) = 30;
    ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block); } return 0; 

}
block内部は構造体の関数を呼び出した:static struct main_block_desc_0 {  size_t reserved;  size_t Block_size;  void (copy)(struct __main_block_impl_0, struct main_block_impl_0);  void (dispose)(struct __main_block_impl_0*);  }
そして、このc++ファイルを分析すると、blockは実際には、構造体を指すポインタコンパイラがblockの内部コードを対応する関数を生成することを知っています.
そしてミアではmでは、通常のint変数を呼び出すと、伝達されたageは実は値伝達であり、_blockはリファレンス伝達!だから、このような結果です!
これはblockに対する基礎的な認識で、次のブログでは、mrcとarcがblockを使う違いを紹介します.読者に役に立つことを望んでいます.