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的语义就行了.基本上只有在写编译器和虚拟机的时候才需要管什么是 ...
随机推荐
- List(JDK1.7)(3)
Vector 实现了一个存储对象的增长数组.如同一个数组,它可以使用一个整型下标来访问元素.但是,vector的大小是可以根据需要增长或收缩的. 每个vector通过维护capacity和capaci ...
- CentOS 7快速入门系列教程(一)
基本命令 ls 列举当前目录下的所有文件夹 ls -l 查看文件还是文件夹 d表示文件夹 -表示文件 ls --help man ls 询问命令 man 3 malloc 查看函数 cd 跳转 ...
- 写一个shell脚本利用wget抓取股票历史数据
今天,大数据部老大交给我一项任务——抓取股票历史数据.于是乎,我自行在网上找了一下,发现wget真真是一个非常强大的linux下载工具.我已经被深深震撼到了.下面叙述今天的一些过程,还是比较坎坷的. ...
- 【leetcode 简单】 第八十七题 两整数之和
不使用运算符 + 和-,计算两整数a .b之和. 示例: 若 a = 1 ,b = 2,返回 3. class Solution: def getSum(self, a, b): "&quo ...
- JavaScript的基本介绍
JavaScript入门介绍 输出语句:document.write() 1.执行顺序:从上到下,每一天语句是要加分号的,如果不加的话,浏览器会默认帮你自动添加,分号. 2.注释:一行注释就是 ...
- 【译】第十篇 Replication:故障排除
本篇文章是SQL Server Replication系列的第十篇,详细内容请参考原文. 复制故障排除是一项艰巨的任务.在任何复制设置中,都涉及到很多移动部件,而可用的工具并不总是很容易识别问题.Th ...
- 苹果手机浏览器$(document).on(“click”,function(){})点击无效的问题
<label class="js_highlight" style="display: inline-block;float: left;width: 50%;&q ...
- AutoCAD DevTV-AUTOCAD二次开发资源合集
Webcast Language Date AutoCAD .Net - Session 2 English 13-Sep-12 AutoCAD .Net - Session 1 English 6- ...
- vue+hbuilder监听安卓返回键问题
1.监听安卓返回键问题 效果:在一级页面按一下返回键提示退出应用,按两下退出应用;在其它页面中,按一下返回上个历史页面 1 2 import mui from './assets/js/mui.min ...
- from setuptools import setup ImportError: No module named setuptools【转】
转自:http://www.cnblogs.com/chinacloud/archive/2010/12/24/1915644.html from setuptools import setupImp ...