C++雾中风景7:闭包

原本说好要聊一聊命名空间的,由于最近在看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源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索