前言


我们经常所编程语言的的进步速度是落后于硬件的发展速度的。

但是最近几年,闭包语法在各个语言中都有自己的体现形式,例如

  •  C语言中使用函数指针作为回调函数的入口;

  •  Java和C#语言中的Lambda语法表达式;

  •  Objective-C语言中的Blocks语法;

  •  C#语言中的Delegates语法;

  •  C++语言中的Functions对象;

历史


Peter J. Landin 在1964年将术语 闭包 定义为一种包含 环境成分 和 控制成分 的实体,用于在他的SECD 机器上对表达式求值。Joel Moses 认为是 Landin 发明了 闭包 这一术语,用来指代某些其开放绑定(自由变量)已经由其语法环境完成闭合(或者绑定)的 lambda 表达式,从而形成了 闭合的表达式,或称闭包。

使用方法


C++语言中的Functions对象:

C++11标准开始支持闭包,这是一种特殊的函数对象,由特殊的语言结构—— lambda表达式 自动构建。

C++闭包中保存了全部nonlocal变量的拷贝或引用。

如果是对外界环境中的对象的引用,且闭包执行时该外界环境的变量已经不存在(如在调用栈上已经unwinding),那么可导致undefined behavior,因为C++并不扩展这些被引用的外界环境的变量的生命期。

常见代码如下:

//
// main.cpp
// Interface
//
// Created by lewis on 4/30/15.
// Copyright (c) 2015 lewis. All rights reserved.
// #include <iostream>
#include <string>
#include <vector> using namespace std; //构造string向量
vector<string> GetNameList()
{
static vector<string> names; names.push_back("刘辉");
names.push_back("李静波");
names.push_back("崔亚允");
names.push_back("赵雅");
names.push_back("管辉");
names.push_back("白志刚");
names.push_back("王斌");
names.push_back("白雅静");
names.push_back("张浩"); return names;
} void foo(string myname) {
vector<string> names = GetNameList(); //通过遍历string向量,使用闭包完成判断条件
vector<string>::iterator i = find_if(names.begin(), names.end(), [&](const string& s){ //判断操作值与参数相等是否相等
return s == myname;
}); //输出判断得到的结果
cout <<(string)(*i) << endl;
} int main(int argc, const char * argv[]) { foo("刘辉"); return 0;
}

1、声明闭包变量

C++中闭包的声明语法,要使用 function 类型来声明变量,如下所示

std::function<float(float)> colsure;

其中,第一个 float 代表了闭包的返回值类型,第二个 float 代表了闭包的参数数据类型为浮点型

2、赋值闭包变量

C++中闭包的赋值语法,要使用 [=] 或 [&] 符号开头,如下所示

colsure = [=](float f) {
f += 10.0f;
return f;
};

其中, [=] 代表了我们将要进行的闭包传值是单向赋值

[&] 在使用过程中,经常作为引用传值使用,如下所示

std:function<float(float&)> col;
col = [&](float& f){
f += 10.0f;
return f;
};

3、使用闭包变量

使用 [=] 和 [&] 声明并且赋值后的闭包变量,在使用结束后的结果如下

//声明一个浮点型变量
float floatValue = 1.0f;
//声明计算结果浮点型变量
float resultValue = 0.0f; //使用[=]类型的闭包变量
resultValue = colsure(floatValue);
//输入结果
std::cout<<floatValue<<":"<<resultValue<<endl; //使用[&]类型的闭包变量
resultValue = col(floatValue);
std::cout<<floatValue<<":"<<resultValue<<endl;

通过打印的结果,

1.0:10.0
10.0:10.0

[=] 和 [&] 分别代表了值传递和引用传递的两种方式。

Objective-C中的Blocks变量:

Blocks语法支持的系统版本为OS X 8或者更高版本,iOS 4或者更高版本.

常见的代码如下:

//
// main.m
// BlockSample
//
// Created by lewis on 4/30/15.
// Copyright (c) 2015 lewis. All rights reserved.
// #import <Foundation/Foundation.h> NSArray *GetNameList()
{
static NSMutableArray *names = nil; if (names == nil) {
names = [[NSMutableArray alloc] init];
[names addObject:@"刘辉"];
[names addObject:@"崔亚允"];
[names addObject:@"李静波"];
[names addObject:@"赵雅"];
[names addObject:@"管辉"];
[names addObject:@"王斌"];
[names addObject:@"张浩"];
} return names;
} void foo(NSString *myname)
{
//获取到姓名列表
NSArray *names = GetNameList(); //通过遍历数组对象,使用Block进行判断
NSInteger index = [names indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return [obj isEqualToString:myname];
}]; //输出结果
NSLog(@"%@",names[index]);
} int main(int argc, const char * argv[])
{
foo(@"崔亚允");
return 0;
}

1、声明Block语法变量

float(^block)(float);

我们会发现,Blocks语法变量的声明语法与函数指针变量的声明语法 float(*pointer)(float); 非常类似,只是在运算符号上有区别;

2、赋值Block语法变量

block = ^ (float f){
f += 10.0f;
return f;
};

在对Blocks变量进行赋值时,要注意所有的Block变量都是用 "^" 运算符号来开头,并且有返回值类型的Block变量,在Block代码块内部的return 返回类型要相同。

详细的Block语法参考:http://www.cnblogs.com/daxiaxiaohao/p/3913467.html

C#语言中的Lambda表达式:

Lambda表达式实在C#4中出现的语法糖,用来提高程序的开发效率,简化Func类型变量和delegate对象的写法。

常见的代码如下:

using System;
using System.Collections.Generic; namespace LambdaSample
{
class MainClass
{
public static List<string> GetNameList()
{
List<string> names = new List<string> (); names.Add ("刘辉");
names.Add ("崔亚允");
names.Add ("李静波");
names.Add ("赵雅");
names.Add ("管辉");
names.Add ("白志刚"); return names;
} public static void foo(string myname)
{
//获取姓名列表
List<string> names = GetNameList (); //通过Lambda表达式作为判断条件进行查询
string result = names.Find ((x) => {
return x == myname;
}); //输入查询结果
Console.WriteLine(result);
} public static void Main (string[] args)
{
//测试
foo ("崔亚允");
}
}
}

1、声明C#语言中的Lambda表达式变量

在C#语言中,可以通过 Func 类型来声明Lambda变量,如下所示:

Func<float,float> func;

或者使用 delegate 类型来声明Lambda变量,如下所示:

//定义一个delegate类型Interface
delegate float Interface(float x); public static void Main (string[] args)
{
//使用Interface类型来声明Lambda变量
Inteface inter_func;
}

2、赋值C#语言中的Lambda表达式变量

在C#语言中,使用 => goes to 运算符来生成变量,如下所示:

func = (x) => {
x += 10.0f;
return x;
};

=> goes to运算符的左边是闭包类型的浮点型参数,右边是闭包变量准备进行的逻辑运算,以 {} 包括。

3、使用C#语言中的Lambda表达式变量

和调用函数一样,如下所示:

//声明Func类型变量
Func<float,float> func; //为func赋值Lambda闭包
func = (x) => {
x += 10.0f;
return x;
}; float floatValue = 1.0f;
float resultValue = 0.0f; //调用func变量,计算结果并且赋值给resultValue
resultValue = func (floatValue); //进行输出
Console.WriteLine (resultValue);

总结


其实在计算机科学中,闭包Closure)是词法闭包Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。

需要注意的一点是

闭包一词经常和匿名函数混淆。这可能是因为两者经常同时使用,但是它们是不同的概念!!!!

[iOS、Unity、Android] 浅谈闭包的使用方法的更多相关文章

  1. 浅谈 js 字符串 trim 方法之正则篇

    原文:浅谈 js 字符串 trim 方法之正则篇 关于 trim 其实没啥好说的,无非就是去除首位空格,对于现代浏览器来说只是简单的正则 /^\s+|\s+$/ 就可以搞定了.而且支持中文空格   等 ...

  2. 浅谈 js 字符串 search 方法

    原文:浅谈 js 字符串 search 方法 这是一个很久以前的事情了,好像是安心兄弟在学习js的时候做的练习.具体记不清了,今天就来简单分析下 search 究竟是什么用的. 从字面意思理解,一个是 ...

  3. IOS 浅谈闭包block的使用

    前言:对于ios初学者,block通常用于逆向传值,遍历等,会使用,但是可能心虚,会感觉block很神秘,那么下面就一起来揭开它的面纱吧. ps: 下面重点讲叙了闭包的概念,常用的语法,以及访问变量, ...

  4. iOS应用架构浅谈

    (整理至http://www.cocoachina.com/ios/20150414/11557.html) 缘由 从事iOS工作一年多了,主要从事QQ钱包SDK开发和财付通app维护,随着对业务的慢 ...

  5. iOS开发之浅谈MVVM的架构设计与团队协作

    今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...

  6. 浅谈 js 对象 toJSON 方法

    前些天在<浅谈 JSON.stringify 方法>说了他的正确使用姿势,今天来说下 toJSON 方法吧.其实我觉得这货跟 toString 一个道理,他是给 stringify 方法字 ...

  7. iOS 或者Android调用vue.js 里面的方法

    1.原生调用vue.js 某个vue组件下的方法. 比如**.vue里面有个这样的方法: 如果这样的话,在iOS或者Android里面是调用不了这个ajax方法的. 需要在**.vue (我的版本是v ...

  8. Android 浅谈 设计与屏幕适配 【1.6235449734285716】

    extends: http://www.ui.cn/detail/45435.html http://www.2cto.com/kf/201501/372699.html http://www.cnb ...

  9. iOS UIView 动画浅谈

    UIView 等会效果简单实现,哪一个登录页面的demo来举例子吧. + (void)animateWithDuration:(NSTimeInterval)duration animations:( ...

随机推荐

  1. 【一题多解】 map 二分 hash trie poj 2503

    各种方式解这道题!! 利用map 超时了 #include <iostream> #include <string> #include <map> using na ...

  2. hibernate缓存机制(二级缓存)

    一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数 ...

  3. web项目的集成测试:模拟点击

    利用模拟点击的方式进行集成测试,我们准备用google,Firefox和ie三种浏览器测试. 其中除了Firefox是模拟点击的鼻祖不需要插件外,谷歌和ie需要另外下载插件 chromedriver. ...

  4. 大学二三事——那些人(1)

    校歌墙的对面是一座历史比较悠久的建筑,以前叫做12号楼,后来改成了"诚"字楼. 在诚字楼一楼昏暗的走廊上,你总是能看见一位大概四五十岁的大叔,有时他会指着挂在墙上的学校简介,一个人 ...

  5. 在win7/8/10鼠标右键添加按下SHIFT键时弹出的“在此处打开命令窗口”

    Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\Drive\shell\cmd]@="@shell32.dll,-8506&q ...

  6. Java项目开发第二天

    相对来说今天还是轻松了挺多的,好了,刚刚跑完步,今天心情不错,直接进入主题,就不废话了. (PS:室友都去准备迎新了,老大也是,还好都将课本留给我了,可以好好的看看书了,好好学习,天天向上.) 图形用 ...

  7. awk 数组排序-- asort 与 asorti

    两者排序区别: asort 是对数组的值进行排序,并且会丢掉原先键值: asorti是对数组的下标进行排序. 数据文件: 12 34 78 90 23 45 1. awk是关联数组.for-in循环输 ...

  8. 扩展欧几里得 POJ 1061

    感觉这道题目的数据好水啊...我的代码我都觉得姿势特别奇怪...竟然还过了... 好吧,原来不是姿势奇怪,而是逆元需要用的时候是余数也需要的时候,这里的余数是不需要的,所以就AC了 就说一下碰到的问题 ...

  9. 安卓开发之探秘蓝牙隐藏API(转)

    源:http://www.cnblogs.com/xiaochao1234/p/3793172.html 上次讲解Android的蓝牙基本用法,这次讲得深入些,探讨下蓝牙方面的隐藏API.用过Andr ...

  10. OCR图片识别引擎

    OCR引擎 OCR(Optical Character Recognition)是指使用扫描仪或数码相机对文本资料进行扫描成图像文件,然后对图像文件进行分析处理,自动识别获取文字信息及版面信息的软件. ...