设为首页 加入收藏

TOP

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

  这里主要讨论的是C语言的扩展特性block。该特性是Apple为C、C++(www.cppentry.com)、Objective-C增加的扩展,让这些语言可以用类Lambda表达式的语法来创建闭包。前段时间,在对CoreData存取进行封装时(让开发人员可以更简洁快速地写相关代码),我对block机制有了进一步了解,觉得可以和C++(www.cppentry.com) 11中的Lambda表达式相互印证,所以最近重新做了下整理,分享给大家。

  0. 简单创建匿名函数

  下面两段代码的作用都是创建匿名函数并调用,输出Hello, World语句。分别使用Objective-C和C++(www.cppentry.com) 11:

  [cpp]

  ^{printf("Hello, World!\n"); } ();

  [cpp] view plaincopy

  [] { cout << "Hello, World" << endl; } ();

  Lambda表达式的一个好处就是让开发人员可以在需要的时候临时创建函数,便捷。

  在创建闭包(或者说Lambda函数)的语法上,Objective-C采用的是上尖号^,而C++(www.cppentry.com) 11采用的是配对的方括号[]。

  不过“匿名函数”一词是针对程序员而言的,编译器还是采取了一定的命名规则。

  比如下面Objective-C代码中的3个block,

  [cpp]

  #import <Foundation/Foundation.h>

  int(^maxBlk)(int, int) = ^(intm, intn){ returnm > n m : n; };

  int main(intargc, constchar * argv[])

  {

  ^{printf("Hello, World!\n"); } ();

  int i = 1024;

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

  blk();

  return 0;

  }

  会产生对应的3个函数:

  [cpp]

  __maxBlk_block_func_0

  __main_block_func_0

  __main_block_func_1

  可见函数的命名规则为:__{$Scope}_block_func_{$index}。其中{$Scope}为block所在函数,如果{$Scope}为全局就取block本身的名称;{$index}表示该block在{$Scope}作用域内出现的顺序(第几个block)。

  1. 从语法上看如何捕获外部变量

  在上面的代码中,已经看到“匿名函数”可以直接访问外围作用域的变量i:

  [cpp]

  int i = 1024;

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

  blk();

  当匿名函数和non-local变量结合起来,就形成了闭包(个人看法)。

  这一段代码可以成功输出i的值。

  我们把一样的逻辑搬到C++(www.cppentry.com)上:

  [cpp]

  inti = 1024;

  auto func = [] { printf("%d\n", i); };

  func();

  GCC会输出:错误:‘i’未被捕获。可见在C++(www.cppentry.com)中无法直接捕获外围作用域的变量。

  以BNF来表示Lambda表达式的上下文无关文法,存在:

  [cpp]

  lambda-expression : lambda-introducer lambda-parameter-declarationopt compound-statement

  lambda-introducer : [ lambda-captureopt ]

  因此,方括号中还可以加入一些选项:

  [cpp]

  []        Capture nothing (or, a scorched earth strategy )

  [&]       Capture any referenced variable by reference

  [=]       Capture any referenced variable by making a copy

  [=, &foo] Capture any referenced variable by making a copy, but capture variable foo by reference

  [bar]     Capture bar by making a copy; don't copy anything else

  [this]    Capture the thispointer of the enclosing class

  根据文法,对代码加以修改,使其能够成功运行:

  [cpp]

  bash-3.2# vi testLambda.cpp

  bash-3.2# g++-4.7 -std=c++11 testLambda.cpp -o testLambda

  bash-3.2# ./testLambda

  1024

  bash-3.2# cat testLambda.cpp

  #include <iostream>

  using namespace std;

  int main()

  {

  int i = 1024;

  auto func = [=] { printf("%d\n", i); };

  func();

  return 0;

  }

  bash-3.2#

           

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

评论

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