C++ Primer : 第十章 : 泛型算法 之 lambda表达式和bind函数
来源:互联网 发布:gif动态图片制作软件 编辑:程序博客网 时间:2024/05/20 21:21
一、lambda表达式
lambda表达式原型: [capture list] (parameter list) -> retrue type { function body }
一个lambda表达式表示一个可调用的代码单元,可以理解为一个未命名的内联函数。一个lambad表达式包含 : 一个捕获列表,一个参数列表,一个返回类型和函数体。
但与函数不同的是,lambda可能定义在函数内部。 lambda可以忽略参数列表和返回类型,但必须包含捕获列表和函数体。
如果一个lambda的函数体包含任何单一的return语句之外的内容,且未指定返回类型,则返回void
1. 捕获列表
lambda的捕获列表只用于局部的非static变量,它可以直接使用局部static变量和它所在函数之外声明的名字。lambda只有在其捕获列表中捕获了一个它所在函数中的局部非static变量,它的函数体才可以使用该变量。
捕获方式有两种 : 值捕获和引用捕获 另外还有 隐式捕获
值捕获 : 和传值参数类似,lambda进行值捕获的时候拷贝变量,与参数不同,lambda的值捕获进行拷贝时是创建时拷贝,而不是调用时拷贝。
引用捕获:引用捕获和引用传递参数类似,不拷贝变量,但应该注意的是,我们lambda在进行引用捕获时,要确保被引用的对象在lambda执行的时候是存在的。
隐式捕获 : 值捕获和引用捕获都是显示列出了我们想要捕获的变量,我们还可以让编译器根据lambda体中的代码来推断我们要使用哪些变量,我们需要在捕获列表里写一个 & 或者 =。 &告诉编译器采用引用捕获方式,= 是值捕获方式。还可以混合使用显示和隐式捕获方式。
当我们混合使用显示和隐式捕获方式时,捕获列表中的第一个元素必须是一个&或=, 指定默认的捕获方式为值或引用。 而且显示捕获的变量必须使用与隐式捕获不同的凡是。如果隐式捕获时引用方式,则显示捕获必须是值方式。
默认情况下,值捕获的变量,lambda不会改变其值,如果我们希望改变一个被值捕获的变量,就把关键字 mutable 跟随在参数列表后
void func(){ size_t i = 0; auto f = [i] () mutable { return ++i; } cout << "i = " << i << endl;}输出 i = 1
2. 指定lambda返回类型
前面我们说,如果一个lambda的函数体包含任何单一的return语句之外的内容,且未指定返回类型,则返回void。
transform(v.begin(), v.end(), v.begin(), [] (int i) {if (i < 0) return -i; else return i;})
这段程序将产生错误,因为编译器推断出lambda返回一个void,但它返回一个int值。
我们需要使用尾置返回类型来指定lambda的返回类型:
transform(v.begin(), v.end(), v.begin(), [] (int i) -> int {if (i < 0) return -i; else return i;})
二、参数绑定 bind函数
标准库bind函数定义在头文件 <functional>中,它接受一个可调用对象,来生成一个新的可调用对象来适用原对象的参数列表。
调用bind的一般形式为:
auto newCallable = bind(callable, arg_list);
newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的callable的参数。当我们调用newCallable时,newCallable会调用callable,并传递给callable对应的参数arg_list。
arg_list中会出现形如 _n的名字,n是一个整数,从1开始。这些参数是"占位符", 表示newCallable的参数。它们占据了传递给newCallable的参数的位置,数值n表示生成的可调用对象中参数的位置。
名字 _n 都定义在一个名为placeholders的命名空间里,而这个命名空间则包含在std命名空间里。我们要用这些占位符时,就需要using声明:
using std::placeholders::_n
与bind一样,placeholders命名空间也定义在 <functional> 头文件中。
bind的参数
例:
// g是一个有两个参数的可调用对象auto g = bind(f, a, b, _2, c, _1);
这样一来,我们传递给g对象的参数,按位置绑定到占位符上,第一个参数绑定到_1, 第二个绑定到_2.
实际上,这个bind调用会将 g(_1, _2) 映射为 f (a, b, _2, c, _1),例如调用g(X, Y)会调用 f (a, b, Y, c, X)
默认情况下,bind的那些不是占位符的参数被拷贝到返回的可调用对象中。对有些绑定的参数我们希望以引用方式传递,或是要绑定参数的类型无法拷贝。
// 错误,不能拷贝osfor_each(words.begin(), words.end(), bind(print, os, _1, ' '));
我们不能拷贝一个ostream对象,如果我们希望传递给bind一个对象但不拷贝它,就必须使用标准库ref函数。
函数ref返回一个对象,包含给定的引用。还有一个cref函数,生成一个const引用的类。ref和cref函数也定义在 <functional>头文件中。
0 0
- C++ Primer : 第十章 : 泛型算法 之 lambda表达式和bind函数
- C++primer--lambda表达式-参数绑定之bind
- [C++] 通用算法、函数对象、lambda表达式、bind
- 《C++ Primer》读书笔记第十章-1-初识泛型算法 And Lambda
- C++ Primer : 第十章 : 泛型算法 之 只读、写和排序算法
- C++primer(第五版)第十章 泛型算法
- 《C++primer(第五版)》学习之路-第十章:泛型算法
- c++ primer 读书笔记之第十章 泛型算法
- 谓词,lambda表达式和bind
- C++ Primer之泛型算法lambda笔记
- 【C#】之匿名函数及Lambda表达式
- C#lambda表达式和匿名函数
- C++ Primer :第十章 :泛型算法之再探迭代器以及其他算法
- 泛型算法 lambda表达式
- c++primer(第五版) 第十章 泛型算法习题答案
- 2016/12/08C++Primer学习笔记:第十章 泛型算法
- 《C++primer(第五版)》学习笔记-第十章:泛型算法
- c++ primer第五版(中文)习题答案 第十章第三节第二小节-lambda表达式
- 安卓自定义控件(图像循环切换)
- Linux下boost安装、测试教程
- Leetcode#72||Edit Distance
- libcurl源码编译
- IT痴汉的工作现状41-亲历招投标
- C++ Primer : 第十章 : 泛型算法 之 lambda表达式和bind函数
- 响应式布局
- 引导选择失败
- Egg dropping puzzle
- 【Ajax技术】解决XHR与中文乱码问题
- 解决虚拟机提示 “VMware Workstation cannot connect to the virtual machine” 的问题
- Objective-C 集合对象的内存管理
- android技术层次
- xcode自动选择证书 Setting up Xcode to automatically manage your provisioning profiles