lambda表达式
2023年12月24日 2023年12月26日
lambda expression
实则是重载了调用运算符 ()
的类的一个实例
通过捕获列表, 可以弥补谓词只有两个形参的不足
[capture list] (parameter list) -> return type { function body }
和函数比较
函数 | lambda表达式 | |
---|---|---|
返回类型 | O | O; 尾置返回类型 |
参数列表 | O | O |
函数体 | O | O |
名称 | O | X |
可以在函数内部定义 | X | O |
捕获列表 | - | O |
- 类的构造函数没有返回类型. 函数的返回类型不可省略
- 函数的参数列表不可省略
lambda表达式没有名称
- 其常常作为参数使用, 在传参时给出定义
- 可以作为对象参与赋值
lambda表达式组成
可以省略 | |
---|---|
捕获列表 | X |
参数列表 | O |
返回类型 | O |
函数体 | X |
- 捕获列表为空也需要给出
[]
- lambda表达式不支持默认实参: 调用时, 实参与形参的数目相等
- 调用lambda表达式时, 实参与形参的类型必须匹配
- 省略参数列表即参数列表为空
- 省略返回类型时
- 如果lambda表达式的函数体只包含单一return语句, 编译器根据返回值中推断出返回类型
- 如果lambda表达式包含return语句外的任何语句, 编译器认为返回类型为void
- 如果lambda表达式的函数体只包含单一return语句, 编译器根据返回值中推断出返回类型
示例
-
定义lambda表达式, 省略参数列表和返回类型
- 调用时不需要传递参数
- 从return语句中推断出返回类型为int
lambda表达式的调用方法与普通函数一样,使用调用运算符
()
f是可调用对象,不接受参数,返回42
1auto f = [] { return 42; }; 2 3cout << f() << endl;
- 调用时不需要传递参数
-
使用lambda表达式实现isShorter
将lambda表达式作为参数使用, 传参时给出定义stable_sort需要比较两个元素时,会调用传入的lambda表达式
1stable_sort(words.begin(), words.end(), [](const string &a, const string &b) { return a.size() < b.size(); });
lambda表达式可以直接在函数体内使用具有静态属性的对象
1[](const string &s) 2{ 3 std::cout << s << " "; 4} 5 6// lambda表达式的捕获列表为空 7// 函数体中使用的s来自参数列表 8// 函数体中使用的std::cout来自头文件iostream
遍历序列元素
foreach
给出序列的所有元素, 使用迭代器范围: [b, e)
给出一元谓词: 对输入序列中的每个元素调用给定的一元谓词
1for_each(words.begin(), words.end(), [](const string &s) { cout << s << " "; }); 2cout << endl;
捕获列表
capture list
lambda表达式通常定义在块中. 可以在捕获列表中填入当前可访问的局部变量的名称, 在函数体中使用局部变量的同名引用或同名拷贝
使用逗号分隔捕获的局部变量
通常为空
捕获列表为空时, 不使用块内任何局部变量
示例
lambda表达式捕获变量sz, 有唯一参数a
根据return语句推断返回类型为bool
1[sz](const string &a) 2{ 3 return a.size() >= sz; 4}
在序列中查找(首个)匹配元素
find_if
给出序列的所有元素, 使用迭代器范围: [b, e)
给出一元谓词: 对输入序列中的每个元素调用给定的一元谓词
返回迭代器:
- 如果存在匹配元素, 返回指向第一个匹配元素的迭代器
- 无匹配元素, 返回尾后迭代器
示例
在words的诸多元素中,查找第一个长度不小于sz的元素,返回指向该元素的迭代器
1auto wc = find_if(words.begin(), words.end(), [sz](const string &a){ return a.size() >= sz; }); 2 3auto count = words.end() - wc; 4// 元素已经根据长度从小到大排序,从wc开始,所有元素的长度都不小于sz 5// count为words中所有长度不小于sz的元素的个数 6 7cout << count << " " << make_plural(cout, "word", "s") << " of length " << sz << " or longer" << endl; 8// make_plural:根据count是否大于1,输出word或words 9// 输出长度不小于sz的单词的个数
完整示例: biggies函数
输出不小于给定长度的单词数目, 并输出这些单词
1void biggies(vector<string> &words, vector<string>::size_type sz) 2{ 3 elimDups(word); 4 // 对单词进行排序,去除重复单词 5 6 // stable_sort(words.begin(), words.end(), isShorter); 7 8 stable_sort(words.begin(), words.end(), [](const string &a, const string &b) 9 { return a.size() < b.size(); }); 10 // 将单词按长度从小到大排序 11 12 auto wc = find_if(words.begin(), words.end(), [sz](const string &a){ return a.size() >= sz; }); 13 // 查找第一个不小于指定长度的元素,返回指向该元素的迭代器 14 15 auto count = words.end() - wc; 16 // 从wc开始,所有元素都不小于sz 17 // count为words中所有长度不小于sz的元素的个数 18 19 cout << count << " " << make_plural(cout, "word", "s") << " of length " << sz << " or longer" << endl; 20 // make_plural:根据count是否大于1,输出word或words 21 // 输出长度不小于sz的单词的个数 22 23 // 输出长度不小于sz的单词 24 for_each(wc, words.end(), [](constt string &s) {cout << s << " "; }); 25 cout << endl; 26}