C++雾中风景7:闭包
本来说好要聊一聊命名空间的,因为最近在看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:闭包的更多相关文章
- 《Web 前端面试指南》1、JavaScript 闭包深入浅出
闭包是什么? 闭包是内部函数可以访问外部函数的变量.它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量. 内部函数不仅可以访问外 ...
- 干货分享:让你分分钟学会 JS 闭包
闭包,是 Javascript 比较重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,很难从定义去理解它.因此,本文不会对闭包的概念进行大篇幅描述 ...
- 深入浅出JavaScript之闭包(Closure)
闭包(closure)是掌握Javascript从人门到深入一个非常重要的门槛,它是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现.下面写下我的学习笔记~ 闭包-无处不 ...
- javascript之闭包理解以及应用场景
半个月没写博文了,最近一直在弄小程序,感觉也没啥好写的. 之前读了js权威指南,也写了篇博文,但是实话实说当初看闭包确实还是一头雾水.现在时隔一个多月(当然这一段时间还是一直有在看闭包的相关知识)理解 ...
- js闭包 和 prototype
function test(){ var p=200; function q(){ return p++; } return q; } var s = test(); alert(s()); aler ...
- js闭包for循环总是只执行最后一个值得解决方法
<style> li{ list-style: none;width:40px;height: 40px;text-align:center;line-height: 40px;curso ...
- JavaScript学习笔记(二)——闭包、IIFE、apply、函数与对象
一.闭包(Closure) 1.1.闭包相关的问题 请在页面中放10个div,每个div中放入字母a-j,当点击每一个div时显示索引号,如第1个div显示0,第10个显示9:方法:找到所有的div, ...
- 带你一分钟理解闭包--js面向对象编程
上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...
- 如何设计一门语言(七)——闭包、lambda和interface
人们都很喜欢讨论闭包这个概念.其实这个概念对于写代码来讲一点用都没有,写代码只需要掌握好lambda表达式和class+interface的语义就行了.基本上只有在写编译器和虚拟机的时候才需要管什么是 ...
随机推荐
- 【转】Elastic日报 第576期 (2019-04-05)
1.Elasticsearch性能测试实践http://t.cn/EiRzFiI2.监控Elasticsearch的插件推荐http://t.cn/EiRzFix3.支持机器数据的可扩展Elastic ...
- Java并发编程原理与实战三十六:阻塞队列&消息队列
一.阻塞队列 1.阻塞队列BlockingQueue ---->可以理解成生产者消费者的模式---->消费者要等待到生产者生产出来产品.---->而非阻塞队列ConcurrentLi ...
- 安装python包时遇到"error: Microsoft Visual C++ 9.0 is required"的简答
简答 在Windows下用pip安装Scrapy报如下错误, error: Microsoft Visual C++ 9.0 is required (Unable to find vcvarsall ...
- 【BZOJ】3453: tyvj 1858 XLkxc 拉格朗日插值(自然数幂和)
[题意]给定k<=123,a,n,d<=10^9,求: $$f(n)=\sum_{i=0}^{n}\sum_{j=1}^{a+id}\sum_{x=1}^{j}x^k$$ [算法]拉格朗日 ...
- UVA1386 【Cellular Automaton】题解
题面:UVA1386 Cellular Automaton 矩阵乘法+快速幂解法: 这是一个比较裸的有点复杂需要优化的矩乘快速幂,所以推荐大家先做一下下列洛谷题目练练手: (会了,差不多就是多倍经验题 ...
- JS中数组那些事~
今天闲的没事,看了一些关于数组的操作,好久木有用过,很多都已经忘记的差不多了,所以今天花了一个小时写了一些demo,准备备份一下方便以后使用~~~ 下面是一些工作当中,经常用到的数组的方法,小伙伴可以 ...
- c# 生成随机N位数字串(每位可以重复)
/// <summary> /// 生成随机数字窜 /// </summary> /// <param name="Digit">位数</ ...
- [译] 用HTML5捕获音频和视频
原文地址:http://www.html5rocks.com/en/tutorials/getusermedia/intro/ 概述 有了HTML5,我们就可以在不借助Flash或者Silverlig ...
- Print Numbers by Recursion
Print numbers from 1 to the largest number with N digits by recursion. Notice It's pretty easy to do ...
- NB-iot 和 emtc两种技术区别
此前有报道称,工信部正在拟定推动窄频物联网(NB-IoT)标准化,并对NB-IoT模块外形.封装以及针脚定义等提出新规范.业内人士认为,标准出台后将促进物联网规模化商用全面提速,迎来行业成长爆发期. ...