六一的部落格


关关难过关关过,前路漫漫亦灿灿。



lambda expression

实则是重载了调用运算符 () 的类的一个实例

通过捕获列表, 可以弥补谓词只有两个形参的不足

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

和函数比较

函数 lambda表达式
返回类型 O O; 尾置返回类型
参数列表 O O
函数体 O O
名称 O X
可以在函数内部定义 X O
捕获列表 - O
  1. 类的构造函数没有返回类型. 函数的返回类型不可省略
  2. 函数的参数列表不可省略

lambda表达式没有名称

  1. 其常常作为参数使用, 在传参时给出定义
  2. 可以作为对象参与赋值

lambda表达式组成

可以省略
捕获列表 X
参数列表 O
返回类型 O
函数体 X
  1. 捕获列表为空也需要给出 []
  2. lambda表达式不支持默认实参: 调用时, 实参与形参的数目相等
  3. 调用lambda表达式时, 实参与形参的类型必须匹配
  4. 省略参数列表即参数列表为空
  5. 省略返回类型时
    • 如果lambda表达式的函数体只包含单一return语句, 编译器根据返回值中推断出返回类型
    • 如果lambda表达式包含return语句外的任何语句, 编译器认为返回类型为void

示例

  1. 定义lambda表达式, 省略参数列表和返回类型

    • 调用时不需要传递参数
    • 从return语句中推断出返回类型为int

    lambda表达式的调用方法与普通函数一样,使用调用运算符 ()

    f是可调用对象,不接受参数,返回42

    1auto f = [] { return 42; };
    2
    3cout << f() << endl;
  2. 使用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}

lambda表达式


lambda expression

实则是重载了调用运算符 () 的类的一个实例

通过捕获列表, 可以弥补谓词只有两个形参的不足

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

和函数比较

函数 lambda表达式
返回类型 O O; 尾置返回类型
参数列表 O O
函数体 O O
名称 O X
可以在函数内部定义 X O
捕获列表 - O
  1. 类的构造函数没有返回类型. 函数的返回类型不可省略
  2. 函数的参数列表不可省略

lambda表达式没有名称

  1. 其常常作为参数使用, 在传参时给出定义
  2. 可以作为对象参与赋值

lambda表达式组成

可以省略
捕获列表 X
参数列表 O
返回类型 O
函数体 X
  1. 捕获列表为空也需要给出 []
  2. lambda表达式不支持默认实参: 调用时, 实参与形参的数目相等
  3. 调用lambda表达式时, 实参与形参的类型必须匹配
  4. 省略参数列表即参数列表为空
  5. 省略返回类型时
    • 如果lambda表达式的函数体只包含单一return语句, 编译器根据返回值中推断出返回类型
    • 如果lambda表达式包含return语句外的任何语句, 编译器认为返回类型为void

示例

  1. 定义lambda表达式, 省略参数列表和返回类型

    • 调用时不需要传递参数
    • 从return语句中推断出返回类型为int

    lambda表达式的调用方法与普通函数一样,使用调用运算符 ()

    f是可调用对象,不接受参数,返回42

    1auto f = [] { return 42; };
    2
    3cout << f() << endl;
  2. 使用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}