lambda及参数绑定
一、介绍
  对于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及参数绑定的更多相关文章
- 泛型2(lambda表达式/参数绑定)
		
lambda 表达式: Lambda表达式完整的声明格式如下: [capture list] (params list) mutable exception-> return type { fu ...
 - Spring MVC初始化参数绑定
		
初始化参数绑定与类型转换很类似,初始化绑定时,主要是参数类型 ---单日期 在处理器类中配置绑定方法 使用@InitBinder注解 在这里首先注册一个用户编辑器 参数一为目标类型 proper ...
 - SpringMVC初始化参数绑定--日期格式
		
一.初始化参数绑定[一种日期格式] 配置步骤: ①:在applicationcontext.xml中只需要配置一个包扫描器即可 <!-- 包扫描器 --> <context:comp ...
 - SpringMvc中初始化参数绑定
		
初始化参数绑定与类型转换很类似,初始化绑定时,主要是参数类型 ---单日期 在处理器类中配置绑定方法 使用@InitBinder注解 在这里首先注册一个用户编辑器 参数一为目标类型 proper ...
 - @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
		
文章主要讲解request 数据到handler method 参数数据的绑定所用到的注解和什么情形下使用. 简介: handler method 参数绑定常用的注解,我们根据他们处理的Request ...
 - spring 参数绑定
		
部分资料来源: @RequestParam @RequestBody @PathVariable 等参数绑定注解详解 spring学习之@ModelAttribute运用详解 Spring MVC @ ...
 - springmvc的初始化参数绑定
		
一.springmvc的初始化参数绑定 此种和我们之前说的类型转换非常相似,可以看作是一种类型转换 在初始化参数绑定时 重要的是参数类型 -------------------单日期的绑定 二. 配 ...
 - MVC中Action参数绑定的过程
		
一.题外话 上一篇:MVC中Action的执行过程 ControllerContext 封装有了与指定的 RouteBase 和 ControllerBase 实例匹配的 HTTP 请求的信息. 二. ...
 - springmvc参数绑定
		
1. @PathVariable当使用@RequestMapping URI template 样式映射时, 即 someUrl/{paramId}, 这时的paramId可通过 @Pathvaria ...
 
随机推荐
- 关于html5 data-*自定义属性相关注意点和踩过的坑
			
在HTML5中添加了data-*的方式来自定义属性,所谓data-*实际上上就是data-前缀加上自定义的属性名,命名可以用驼峰命名方式,但取值是必需全部使用小写(后面会说),使用这样的结构可以进行数 ...
 - 关于webpack,打包时遇到的错误
			
最近在研究webpack这玩意,然后遇到一个问题,执行npm run build的时候,出现下面这个问题,各种搜索后,各种尝试,都没解决 运行时报错ERROR in ./src/app.vue Mod ...
 - java基础之二分法查找
			
package p1; import java.util.*; public class Sortdob { public static void BubbleSort(int[] arr) { ...
 - CSS3动画--过渡效果
			
CSS3动画--过渡效果 transition 设置四个过渡属性 transition-property 过渡的名称 tr ...
 - SAXParser解析xml文件
			
对于xml的解析,这里学习并演示使用SAXParser进行解析的样例. 使用此种方法无法解析"gb2312"编码的xml文件,因此,此处xml文件编码设置为"UTF-8& ...
 - 2018第一波iOS经典笔试题(现场实拍)
			
序言 作为一个开发者,眼里不仅仅只存在于那一行又一行的代码,更还有那诗和远方. 注明:面试是对自我审视的一种过程,面试题和iOS程序员本身技术水平没任何关联,无论你能否全部答出,都不要对自己产生任何正 ...
 - Centos7中hadoop配置
			
Centos7中hadoop配置 1.下载centos7安装教程: http://jingyan.baidu.com/article/a3aad71aa180e7b1fa009676.html (注意 ...
 - python感悟
			
嗯,对于python我其实也是一知半解,比较擅长java,我就拿java和python进行比较一下吧 1,首先先说简单的程序运行时间问题,对于同等时间复杂度的测试程序,python虽然运行速度没有c快 ...
 - C# Redis实战(二)
			
二.Redis服务 在C# Redis实战(一)中我将所有文件拷贝到了D盘redis文件夹下,其中redis-server.exe即为其服务端程序,双击即开始运行,如图 可以 ...
 - 11.C++-临时对象分析
			
首先来参考以下代码: #include <stdio.h> class Test { int mi; public: Test(int i) { mi = i; } Test() { Te ...