原本说好要聊一聊命名空间的,由于最近在看C++lambda表达式的内容,因此借这个机会咱们来好好聊一聊C++的闭包。python
1.什么是闭包?
闭包(closure)是函数式编程的重要的语法结构。
闭包的概念其实很简单,一言以蔽之:闭包是带有上下文的函数。说白了,就是有状态的函数。也就是说一个局部变量n,在被函数对象给“封闭”在函数里,从而能把值保存了下来,让函数可以保存状态。(其实本质上就是一个类,用纯粹面向对象的方式理解,函数也是一个对象)编程
扯概念很烦,咱们直接上代码来看一看。这里咱们用Python的代码来解释一下闭包。(后续咱们再来详细聊聊C++之中是怎么样实现闭包的):闭包
def getFun(n): return lambda:n + n funA = getFun(10) funB = getFun("abc") print(funA.func_closure[0].cell_contents) print(funB.func_closure[0].cell_contents)
打印结果为:app
10 //funcA的闭包变量 abc //funcB的闭包变量
由上述两个函数咱们看到变量做为一种状态嵌入到函数由getFun返回的函数之中。不一样的语言实现闭包的方式不一样。Python以函数对象为基础,为闭包是经过函数对象的属性来保存闭包的变量。(这里在Python之中是一个tuple,从这里也能够看出,所谓的闭包本质上就是类属性的一个语法糖。)函数式编程
这里闭包解决了编程工做之中的两个痛点:函数
- (1)突破了函数访问变量的做用域。
- (2)能够动态添加函数属性,真是经过这种动态特性,可让咱们实现某些编程任务的时候变得很简洁。
- (3)函数可定制化更佳,提升了函数的可移植性。
闭包的做用有不少,能够在python上实现动态代理,如装饰器等.......这里就不展开聊闭包的使用,接下来咱们要来重点看看在C++之中是如何实现闭包的。工具
2.C++之中的闭包
C++相对于C的优越点就在于C++可以支持面向对象的特性,C语言之中在语法层面是不能支持闭包的。咱们来看看C++之中有几种方式来支持闭包特性:spa
- 重载类的operator() 操做符
第一次看到用法的时候有点震惊,没想到重载()括号操做符以后能够将普通的类转变为Callable对象,当时以为很Tricky。这种用法其实本质上是其余语法糖的基础,咱们来看一看代码:
class Closure { public: Closure(int n):num(n){}; int operator()(int add) { return num + add; } private: int num; }; int main() { Closure clu(20); cout << clu(50) << endl; }
能够看到,重载了()操做符的类Closure摇身一变成为了一个函数,能够直接被调用。同时它也包含了对象成员,经过对象成员保存下来了函数的运行状态。.net
- lambda表达式
喜欢函数式编程的同窗最喜欢使用的工具了(C++11对于C++来讲是一个很重要的版本),lambda表达式能够很方便的让咱们定义一个匿名函数,咱们来看看怎么用lambda表达式来实现闭包:
int main() { int num = 20; function<int(int)> clu = [num](int add) {return num + add;}; cout << clu(50) << endl; }
使用lambda表达式实现一样的功能,代码就简洁明了许多。这里的clu是经过一个匿名类来实现的,因此每一个lambda表达式都是独一无二的,咱们只能使用function或auto来捕获它。这里lambda表达式经过[]操做符捕获外部变量,而且和函数绑定在了一块儿。代理
- 参数绑定
bind函数在C++11之中也被加入了标准库,咱们来看看经过参数绑定是如何实现闭包的:
int addNum(int num,int add) { return add + num; } int main() { auto clu = bind(addNum,placeholders::_1,20); cout << clu(50) << endl; }
经过bind函数,将20绑定到对应的参数add之上,而每次调用clu函数之时,参数会对应到_1的位置,也就是函数addNum的第一个参数num。经过bind的函数,咱们能够将外部变量与和原函数绑定在了一块儿,而且生成了一个新的函数对象。
好的,关于C++之中的闭包就和你们聊到这里,但愿你们在实际Coding之中能够用好它........
本文同步分享在 博客“HappenLee”(CNBlog)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。