C++雾中风景7:闭包

作者: LeeHappen | 来源:发表于2018-02-07 16:25 被阅读0次

本来说好要聊一聊命名空间的,因为最近在看C++lambda表达式的内容,所以借这个机会我们来好好聊一聊C++的闭包。

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)

打印结果为:

10      //funcA的闭包变量
abc     //funcB的闭包变量

由上述两个函数我们看到变量作为一种状态嵌入到函数由getFun返回的函数之中。不同的语言实现闭包的方式不同。Python以函数对象为基础,为闭包是通过函数对象的属性来保存闭包的变量。(这里在Python之中是一个tuple,从这里也可以看出,所谓的闭包本质上就是类属性的一个语法糖。

这里闭包解决了编程工作之中的几个痛点:

  • (1)突破了函数访问变量的作用域。
  • (2)可以动态添加函数属性,真是通过这种动态特性,可以让我们实现某些编程任务的时候变得很简洁。
  • (3)函数可定制化更佳,提高了函数的可移植性。

闭包的作用有很多,可以在python上实现动态代理,如装饰器等.......这里就不展开聊闭包的使用,接下来我们要来重点看看在C++之中是如何实现闭包的。

2.C++之中的闭包

C++相对于C的优越点就在于C++能够支持面向对象的特性,C语言之中在语法层面是不能支持闭包的。我们来看看C++之中有几种方式来支持闭包特性:

  • 重载类的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摇身一变成为了一个函数,可以直接被调用。同时它也包含了对象成员,通过对象成员保存下来了函数的运行状态

  • 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之中可以用好它........

相关文章

  • C++雾中风景7:闭包

    本来说好要聊一聊命名空间的,因为最近在看C++lambda表达式的内容,所以借这个机会我们来好好聊一聊C++的闭包...

  • 第七章 闭包

    c++没有闭包,swift有闭包。c++有些类似的概念是Lambda函数,但是闭包概念更丰富,更完善,更灵活。 闭...

  • c++ 闭包(closure)

     测试c++的闭包功能。代码抄自webrtc。

  • C++ ---- 闭包

    什么是闭包 能够读取其他函数内部变量的函数。 lambda表达式实现闭包 使用bind函数 有兴趣可看这个知乎,传...

  • JavaScript闭包的理解

    前言 在JavaScript中,闭包对于JavaScript的意义无异于指针在c++中的意义。理解闭包是我们掌握J...

  • Swift5.1闭包

    7.闭包 闭包表达式闭包表达式一般形式:{ (参数列表) -> 返回值类型 in statements...

  • swift-闭包

    闭包 闭包定义 闭包简化 - 尾随闭包 闭包参数 闭包返回值 闭包的循环引用

  • 7_闭包

    Swift 的闭包表达式拥有简洁的风格,并鼓励在常见场景中进行语法优化,主要优化如下: 利用上下文推断参数和返回值...

  • #7 swift 闭包

    swift 中的闭包和JS中的匿名函数很像,但是它还有一些其它的特性,其中包括一些看起来很怪异的语法糖,写法看起来...

  • 7.闭包

    sort 函数 func backward(a:Int, b:Int) -> Bool { return a > ...

网友评论

    本文标题:C++雾中风景7:闭包

    本文链接:https://www.haomeiwen.com/subject/qrriaxtx.html