一、介绍

  对于STL中的算法,我们都可以传递任何类别的可调用对象。对于一个对象或一个表达式,如果可以对其使用调用运算符,则称它为可调用的。即,如果e是一个可调用的表达式,则我们可以编写代码e(args),其中args是一个逗号分隔的一个或多个参数的列表。

  一般来说,有四种可调用对象:函数,函数指针,重载了函数调用运算符的类,以及lambda表达式。

二、lambda表达式

1. 概述

  一个lambda表达式表示一个可调用的代码单元。我们可以将其理解为一个未命名的内联函数。与任何函数类似,一个lambda具有一个返回类型、一个参数列表和一个函数体。但与函数不同,lambda可能定义在函数内部。

  一个lambda的通用表达式为:

    [capture list] (parameter list) -> return type { function body }

  举个简单的例子:

auto f = [] { return 42; };
cout << f() << endl; //打印42

注意,忽略括号和参数列表相当于指定了空的参数列表。如果函数体为一条return语句,lambda将根据代码推断返回类型,否则类型为void。

2. 传递参数

  如函数一样,lambda表达式也可以传递参数,但是不同的是,其不能有默认参数。一个lambda调用的实参数目永远要和形参数目相等。

  举个例子:

auto f = [](const string &lhs, const string &rhs)
{ return a.size() < b.size(); };

3. 使用捕获列表

  所谓捕获列表,则是中括号中的参数,表示使用其所在函数中的任何局部变量。捕获的方式有三种:值捕获引用捕获隐式捕获

/*
* 采用值捕获的前提是,变量可以拷贝,
* 被捕获的变量是在创建时拷贝,而非在调用是拷贝。
*/
void fcn1() {
size_t v1 = 42;
auto f = [v1] { return v1; };
v1 = 0;
cout << f() << endl; //打印42
} /*
* 若想要改变捕获列表中的值,
* 可以采用引用捕获,
* 引用捕获保存的是引用。
*/
void fcn2() {
size_t v1 = 42;
auto f = [&v1] { return v1; };
v1 = 0;
cout << f() << endl; //打印0
} /*
* 隐式捕获可以让编译器根据lambda体中的代码来推断我们要使用哪些变量;
* 在捕获列表中。
* &表示采用引用捕获方式,
* =则表示采用值捕获方式。
*/
void biggies(vector<string> &words,
vector<string>::size_type sz,
ostream &os = cout,
char c = ' ')
{
//采用引用捕获
for_each(words.begin(), words.end(),
[&](const string &s) { os << s << c; });
//os显示捕获,采用引用捕获方式;其他(c)为值捕获
for_each(words.begin(), words.end(),
[=, &os](const string &s) { os << s << c; });
}

4. 指定返回类型

  如前面所提到,如果一个lambda体包含return之外的任何语句,则编译器假定此lambda返回void。

//错误示范:编译器推断为void,实际为int
auto f = [](int i) { if(i < 0) return -i; else return i; }; //可以修改为如下
auto f = [](int i) -> int { if(i < 0) return -i; else return i; };

三、参数绑定

  所谓的参数绑定,其实使用bind函数实现的,其定义在functional中。可以将bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象。

  一般的表示形式为:

    auto newCallable = bind(callable, arg_list);

  callable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的callable的参数。

  arg_list中的参数可能包含如_n的名字,其定义在名叫placeholders的命名空间中,而这个命名空间本身定义在std命名空间中。_n为占位符。

  举个简单的例子:

bool check_size(const string &os, string::size_type sz) {
return s.size() > sz;
}
auto check6 = bind(check_size, _1, 6);
stirng s = "hello";
bool b1 = check6(s);

  为了与不支持拷贝的参数绑定,bind经常和ref一起用,ref也定义在头文件functional中,作用是返回一个引用对象。

ostream &print(ostream &os, const string &s, char c) {
return os << s << c;
}
//错误示范
for_each(words.begin(), words.end(), bind(print, os, _1, ' '));
//正确示范
for_each(words.begin(), words.end(), bind(print, ref(os), _1, ' '));

lambda及参数绑定的更多相关文章

  1. 泛型2(lambda表达式/参数绑定)

    lambda 表达式: Lambda表达式完整的声明格式如下: [capture list] (params list) mutable exception-> return type { fu ...

  2. Spring MVC初始化参数绑定

    初始化参数绑定与类型转换很类似,初始化绑定时,主要是参数类型 ---单日期 在处理器类中配置绑定方法  使用@InitBinder注解 在这里首先注册一个用户编辑器 参数一为目标类型   proper ...

  3. SpringMVC初始化参数绑定--日期格式

    一.初始化参数绑定[一种日期格式] 配置步骤: ①:在applicationcontext.xml中只需要配置一个包扫描器即可 <!-- 包扫描器 --> <context:comp ...

  4. SpringMvc中初始化参数绑定

    初始化参数绑定与类型转换很类似,初始化绑定时,主要是参数类型 ---单日期 在处理器类中配置绑定方法  使用@InitBinder注解 在这里首先注册一个用户编辑器 参数一为目标类型   proper ...

  5. @RequestParam @RequestBody @PathVariable 等参数绑定注解详解

    文章主要讲解request 数据到handler method 参数数据的绑定所用到的注解和什么情形下使用. 简介: handler method 参数绑定常用的注解,我们根据他们处理的Request ...

  6. spring 参数绑定

    部分资料来源: @RequestParam @RequestBody @PathVariable 等参数绑定注解详解 spring学习之@ModelAttribute运用详解 Spring MVC @ ...

  7. springmvc的初始化参数绑定

    一.springmvc的初始化参数绑定 此种和我们之前说的类型转换非常相似,可以看作是一种类型转换 在初始化参数绑定时  重要的是参数类型 -------------------单日期的绑定 二. 配 ...

  8. MVC中Action参数绑定的过程

    一.题外话 上一篇:MVC中Action的执行过程 ControllerContext 封装有了与指定的 RouteBase 和 ControllerBase 实例匹配的 HTTP 请求的信息. 二. ...

  9. springmvc参数绑定

    1. @PathVariable当使用@RequestMapping URI template 样式映射时, 即 someUrl/{paramId}, 这时的paramId可通过 @Pathvaria ...

随机推荐

  1. java用Kruskal实现最小生成树

    今天更新这篇文章超级激动,因为我会最小生成树的算法了(其实昨天就开始研究了,只是昨天参加牛客网的算法比赛,结果又被虐了,好难过~) 最小生成树的算法,其实学了数据结构就会有一定的基础,Kruskal算 ...

  2. C#图解教程 第十一章 枚举

    枚举 枚举 设置底层类型和显式值隐式成员编号 位标志 Flags特性使用位标志的示例 关于枚举的补充 枚举 枚举 枚举是由程序员定义的类型与类或结构一样. 与结构一样,枚举是值类型,因此直接存储它们的 ...

  3. Python 爬取 中关村CPU名字和主频

    0.准备工作   1.相关教程         Python 爬虫系列教程:http://cuiqingcai.com/1052.html         Python Web课程:http://ww ...

  4. 通过JDBC连接数据库(MySql为例)并读取数据库信息--JSP基础

    1.先建数据库,数据库名为:employee_DB;然后在数据库employee_DB下建表,表名为employee;最后插入数据. create database employee_DB; use ...

  5. 解决DOS批处理中一个困扰我几十个月的编码问题

    DOS批处理中的编码很有意思.&是命令连接符,先执行&左边的命令,再执行&右边的命令.|是管道操作,把左边的输出当作右边的输入.此外还有&&和||,当要表示这些 ...

  6. 【ZJOI2008】树的统计(树链剖分)

    题面 Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II ...

  7. poj-3169Layout

    题意 当排队等候喂食时,奶牛喜欢和它们的朋友站得靠近些.FJ有N(2<=N<=1000)头奶牛,编号从1到N,沿一条直线站着等候喂食.奶牛排在队伍中的顺序和它们的编号是相同的.因为奶牛相当 ...

  8. linux优化项

    Linux优化: 1.建立普通账号,使用普通用户登陆. 2.处理SELINUX. 3.处理防火墙. 4.精简开机自启动服务.保留sshd,network,crond,rsyslog,sysstat. ...

  9. FCN小小实战

    先说一下前期准备工作:自己的运行环境是Ubuntu16.04+caffe+CPU(这台电脑没有GPU)+python 关于python的搭建就不说了,网上随便一搜,很多参考资源.说一下我配置好caff ...

  10. Delphi的RzDbgrid改变某行的背景色

    本想改变符合条件的行的背景色,试了DbgridEh和原生的Dbgrid直接在DrawColumnCell事件中写重绘代码就好了,But在RzDbgrid就不起效果,查了好一会,百度了一大堆,都是千篇一 ...