设为首页 加入收藏

TOP

C语言中闭包的探究及比较(八)
2013-07-22 17:59:38 来源: 作者: 【 】 浏览:1411
Tags:言中 包的 探究 比较

 

  于是,用__block修饰的int变量i化身为__Block_byref_i_0结构体的最后一个成员变量。

  代码中blk对应的结构体也发生了变化:

  [cpp]

  struct __main_block_impl_0 {

  struct __block_impl impl;

  struct __main_block_desc_0* Desc;

  __Block_byref_i_0 *i; // by ref

  __main_block_impl_0(void*fp, struct__main_block_desc_0 *desc, __Block_byref_i_0 *_i, intflags=0) : i(_i->__forwarding) {

  impl.isa = &_NSConcreteStackBlock;

  impl.Flags = flags;

  impl.FuncPtr = fp;

  Desc = desc;

  }

  };

  __main_block_impl_0发生的变化就是int类型的成员变量i换成了__Block_byref_i_0 *类型,从名称可以看出现在要通过引用方式来捕获了。

  对应的函数也不同了:

  [cpp]

  static void __main_block_func_0(struct __main_block_impl_0 *__cself) {

  __Block_byref_i_0 *i = __cself->i; // bound by ref

  (i->__forwarding->i) = 0; // 看起来很厉害的样子

  printf("%d\n", (i->__forwarding->i));

  }

  main函数也有了变动:

  [cpp]

  int main(intargc, constchar * argv[])

  {

  __block __Block_byref_i_0 i = {(void*)0,(__Block_byref_i_0 *)&i, 0, sizeof(__Block_byref_i_0), 1024};

  void(*blk)(void) = (void(*)(void))&__main_block_impl_0((void*)__main_block_func_0, &__main_block_desc_0_DATA, (struct__Block_byref_i_0 *)&i, 570425344);

  ((void(*)(struct__block_impl *))((struct__block_impl *)blk)->FuncPtr)((struct__block_impl *)blk);

  return 0;

  }

  前两行代码创建了两个关键结构体,特地高亮显示。

  这里没有看__main_block_desc_0发生的变化,放到后面讨论。

  使用__block类型指示符的本质就是引入了__Block_byref_{$var_name}_{$index}结构体,而被__block关键字修饰的变量就被放到这个结构体中。另外,block结构体通过引入__Block_byref_{$var_name}_{$index}指针类型的成员,得以间接访问到外部变量。

  通过这样的设计,我们就可以修改外部作用域的变量了,再一次应了那句话:

  There is no problem in computer science that can’t be solved by adding another level of indirection.

  指针是我们最经常使用的间接手段,而这里的本质也是通过指针来间接访问,为什么要特地引入__Block_byref_{$var_name}_{$index}结构体,而不是直接使用int *来访问外部变量i呢?

  另外,__Block_byref_{$var_name}_{$index}结构体中的__forwarding指针成员有何作用?

  请继续往下看 :)

  5. 背后的内存管理动作

  在Objective-C中,block特性的引入是为了让程序员可以更简洁优雅地编写并发代码(配合看起来像敏感词的GCD)。比较常见的就是将block作为函数参数传递,以供后续回调执行。

  先看一段完整的、可执行的代码:

  [cpp]

  #import <Foundation/Foundation.h>

  #include <pthread.h>

  typedef void (^DemoBlock)(void);

  void test();

  void *testBlock(void*blk);

  int main(int argc, const char * argv[])

  {

  printf("Before test()\n");

  test();

  printf("After test()\n");

  sleep(5);

  return 0;

  }

  void test()

  {

  __block int i = 1024;

  void(^blk)(void) = ^{ i = 2048; printf("%d\n", i); };

  pthread_tthread;

  int ret = pthread_create(&thread, NULL, testBlock, (void*)blk);

  printf("thread returns : %d\n", ret);

  sleep(3);// 这里睡眠1s的话,程序会崩溃

  }

              

首页 上一页 5 6 7 8 9 下一页 尾页 8/9/9
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C语言中的序列点和副作用 下一篇C语言复杂声明的本质与局限

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: