转自:https://www.cnblogs.com/Aion/p/3449756.html

闭包有很多种定义,一种说法是,闭包是带有上下文的函数。说白了,就是有状态的函数。更直接一些,不就是个类吗?换了个名字而已。

一个函数, 带上了一个状态, 就变成了闭包了. 什么叫 "带上状态" 呢? 意思是这个闭包有属于自己的变量, 这些个变量的值是创建闭包的时候设置的, 并在调用闭包的时候, 可以访问这些变量.

函数是代码, 状态是一组变量 ,将代码和一组变量捆绑 (bind) , 就形成了闭包 ,内部包含 static 变量的函数, 不是闭包, 因为这个 static 变量不能捆绑. 你不能捆绑不同的 static 变量. 这个在编译的时候已经确定了.

闭包的状态捆绑, 必须发生在运行时.

闭包的实现

C++ 里使用闭包有3个办法

重载 operator()

因为闭包是一个函数+一个状态, 这个状态通过 隐含的 this 指针传入. 所以 闭包必然是一个函数对象. 因为成员变量就是极好的用于保存状态的工具, 因此实现 operator() 运算符重载, 该类的对象就能作为闭包使用. 默认传入的 this 指针提供了访问成员变量的途径.

事实上, lambda 和 bind 的原理都是这个.

class MyFunctor
{
public:
MyFunctor(float f) : round(f) {}
int operator()(float f) { return f + round; }
private:
float round;
};
float round = 0.5;
MyFunctor f(round);

lambda

c++11 里提供的 lambda表达式就是很好的语法糖. 其本质和手写的函数对象没有区别.

float round = 0.5;
auto f = [=](float f) { return f + round; }

boost::bind/std::bind

标准库提供的 bind 是更加强大的语法糖, 将手写需要很多很多代码的闭包, 浓缩到一行 bind 就可以搞定了.

int boost_func(float f, float round)
{ return f + round; }
float round = 0.5;
boost::function<int(float)> f = boost::bind(boost_func, _1, round);

比较上面三种方式,有一些细节需要注意:

1. closure的状态特指其运行的上下文。 closure将存贮它运行时需要的上下文,从而保证在closure创建时的上下文可以在closure运行时依然有效。

比如round就是closure的上下文。保存上下文的这一特点通常被称作“capture”或者是"bind"。 capture可以自己写,比如MyFuctor f(round); 也可以用boost::bind。

当然最方便的还是让编译器帮你自动完成。编译器将自动识别closure用到的变量,然后创建一个匿名的类,将这个变量保存到匿名类的成员变量中。

C++中有两种capture方式,by value和by reference。写法是[=]和[&]。

需要注意的是,capture by reference是不会修改被capture变量的生命周期的,你要保证被capture的变量在closure运行时是有效的。

这一点不像Java,Java中变量被capture的话,就变成被引用了,从而GC不会回收它。

2. closure的类型是隐藏的,每次创建一个closure,编译器都会创建一个新的类型。

如果你想保存一个clousre时就不是那么直接,因为你不知道它的类型。这时那需要一些模板技巧,可参考boost::function的实现。

简单的方式是直接用std::function来保存。

std::function<int(float)> closure;

closure = [](float f) { return 0.0f };

closure = [](float f) { return 1.0f };

[C++] - 闭包(closure)相关推荐

  1. Scala编程之闭包(closure)

    一.概念 闭包:我们把一个函数与其相关引用环境(变量)组合成一个整体叫做闭包 概念晦涩难懂,下面我们用一个例子说明 二.小例子 def minusxy(x:Int) = (y:Int)=>x-y ...

  2. [转载]深入理解JavaScript闭包(closure)

    最近在网上查阅了不少Javascript闭包(closure)相关的资料,写的大多是非常的学术和专业.对于初学者来说别说理解闭包了,就连文字叙述都很难看懂.撰写此文的目的就是用最通俗的文字揭开Java ...

  3. 【Groovy】闭包 Closure ( 闭包的 delegate 代理策略 | OWNER_FIRST | DELEGATE_FIRST | OWNER_ONLY | DELEGATE_ONLY )

    文章目录 一.闭包的代理策略引入 二.闭包的四种代理策略 一.闭包的代理策略引入 分别在 Groovy 脚本 和 Test 类中定义 fun 方法 , 打印不同的内容 ; 在闭包 Closure 中分 ...

  4. 【Groovy】闭包 Closure ( 闭包类 Closure 简介 | this、owner、delegate 成员赋值及源码分析 )

    文章目录 总结 一.闭包类 Closure 简介 二.闭包类 Closure 中 this.owner.delegate 成员 源码分析 三.分析编译后的字节码文件内容 总结 在闭包中 , 打印 th ...

  5. 【Groovy】闭包 Closure ( 闭包参数绑定 | curry 函数 | rcurry 函数 | ncurry 函数 | 代码示例 )

    文章目录 一.闭包参数绑定 1.闭包参数绑定 curry 函数 2.闭包参数绑定 rcurry 函数 3.闭包参数绑定 ncurry 函数 二.完整代码示例 一.闭包参数绑定 闭包 Closure 提 ...

  6. 【Groovy】闭包 Closure ( 闭包参数列表规则 | 默认参数列表 | 不接收参数 | 接收自定义参数 )

    文章目录 一.闭包参数列表 二.闭包参数列表代码示例 一.闭包参数列表 闭包的参数设置有如下情况 : 不接收参数 : 如果在定义闭包时 , 只写了 " -> " 符号 , 没 ...

  7. 【Groovy】闭包 Closure ( 闭包调用 | 闭包默认参数 it | 代码示例 )

    文章目录 一.调用闭包 二.闭包默认参数 it 三.代码示例 一.调用闭包 执行 Closure 变量 的 call() 方法 , 可以调用该闭包 ; // 定义闭包变量def closure = { ...

  8. 【Groovy】闭包 Closure ( 闭包定义 | 闭包类型 | 查看编译后的字节码文件中的闭包类型变量 )

    文章目录 一.闭包定义 二.闭包类型 三.查看编译后的字节码文件中的闭包类型变量 一.闭包定义 闭包 Closure 是 Groovy 中最常用的特性 , 使用闭包作为参数是 Groovy 语言的明显 ...

  9. Kettle使用_16 闭包Closure Generator树形数据

    Kettle使用_16 闭包Closure Generator树形数据 需求: 通过Kettle的组件实现对树形结构数据的深度(层次)的生成. 解决方法:结合闭包Closure Generator.排 ...

  10. javascript中的闭包closure详解

    文章目录 简介 函数中的函数 Closure闭包 使用闭包实现private方法 闭包的Scope Chain 闭包常见的问题 闭包性能的问题 总结 简介 闭包closure是javascript中一 ...

最新文章

  1. cookie和session常见问题
  2. QT的foreach用法
  3. 循序渐进Python3(十二) --2--  web框架之django简单实现oracle数据库操作
  4. mac下安装mysql-pyhon_mac下安装MySQL-python模块
  5. 【转】Tag的创建和组织
  6. java代码求IP和mac地址
  7. Linux使用jstat命令查看jvm的GC情况(转)
  8. win10屏幕保护色设置
  9. 面试经验|传音控股自动化测试
  10. 国内镜像源的使用,提高下载速度
  11. 打开本地html加载网页慢,电脑检查网速正常但打开网页慢如何解决
  12. 中职教计算机专业发展,中等职业教育中计算机专业教育思考
  13. 倾斜摄影行业背景知识介绍
  14. 技术宅男揭秘:北京机动车摇号真的公平?
  15. linux终端玩fc游戏,在UBuntu下玩FC和街机模拟器
  16. netcat 下载地址
  17. 【Eclipse】--Eclipse折叠代码插件folding
  18. xinxin -用while循环计算皇帝的棋盘
  19. 告诉大家操作系统32位和64位的区别
  20. php 源生 命令行执行

热门文章

  1. php undefined empty,怎样处理php undefined index毛病问题_后端开发
  2. windows使用WSL安装linux子系统
  3. pandas dataframe使用query进行多个条件快速筛选
  4. 用ipad同步mac的屏幕
  5. CSDN Markdown编辑设置图片大小
  6. java nextbyte()_java.util.Scanner.hasNextByte()方法实例
  7. PAI算法组件详解:PLDA
  8. 部署LNMP架构及其应用
  9. 使用LogParser分析IIS网站日志
  10. 让用户研究插上数据的翅膀