《C++ Premier》第5版 第10章 泛型算法 10.3 定制操作(Lambda)读书笔记


类似普通类的数据成员,lambda的数据成员在lambda对象创建时被初始化

返回

返回

  1. 如果一个lambda体包含任何单一return语句之外的内容,且未指定返回类型,则编译器假定此lambda返回void;
    只包含单一return语句时,编译器会根据体中的代码推导出返回类型。
  2. 被推断为返回void的lambda不能返回值;此时如果需要返回能正常执行,需要明确指定lambda的返回类型

捕获列表

捕获列表
类似参数传递,变量的捕获方式也可以是值或引用。

  1. 只用于局部非static变量,
    因为: lambda可以直接使用局部static变量 和 定义在当前函数之外的名字(全局变量);
    对于lambda所在函数中的局部变量,必须通过捕获列表去捕获才能在lambda体中使用;
  2. 引用方式捕获
    当以引用方式捕获一个变量时,必须保证在lambda执行时变量是存在的;
    在lambda体内使用此变量时,实际上使用的是引用所绑定的对象。
  3. 值捕获时
    值捕获的前提是变量可以拷贝;
    与参数不同,被捕获的值是在lambda创建时拷贝,而不是调用时拷贝;
  4. 应该尽量减少捕获的数据量,来避免潜在的捕获导致的问题;
    而且,如果可能的话,应该避免捕获指针或引用。

参数传递

函数内的lambda,

  1. 函数自动传递给lambda表达式的变量,把变量放在参数列表()中。
  2. 函数没有自动传递给lambda表达式的变量,但是该变量在lambda内部需要使用,怎么办?使用捕获列表[ ]去捕获。

混合使用隐式捕获和显示捕获时

混合使用隐式捕获和显示捕获时

  1. 捕获列表中的第一个元素必须是一个&或=,此符号指定了默认捕获方式为引用或值。
  2. 显示捕获的变量必须使用与隐式捕获不同的方式。

何时使用函数?何时使用lambda?

何时使用函数?何时使用lambda?

  1. 对于那种在一两个地方使用的简单操作,lambda表达式是最有用的。
  2. 如果我们需要在很多地方使用相同的操作,通常应该定义一个函数,而不是多次编写相同的lambda表达式。
  3. 类似的,如果一个操作需要很多语句才能完成,通常使用函数更好。
  4. 如果lambda的捕获列表为空,通常可以用函数代替它。!!!
  5. 对于捕获局部变量的lambda,用函数来替换它就不是那么容易了;需要bind()函数 来 绑定参数。!!!
#include <iostream>
#include <string>
#include <vector>
#include <memory> // shared_ptr
#include <algorithm>
#define Print_FuncLine (cout << __func__ << " " << __LINE__ << endl)
using namespace std;

bool isShorter(const string &s1, const string &s2)
{
    return s1.size() < s2.size();
}

void print(vector<string> &wo)
{
    cout << "size: " << wo.size() << endl;
    for (const string &s : wo)
    {
        cout << s << " ";
    }
    cout << endl
         << endl;
}

void elimDups(vector<string> &wo)
{
    cout << "排序前" << endl;
    Print_FuncLine;
    print(wo);

    //按字典排序
    sort(wo.begin(), wo.end());

    cout << "排序后" << endl;
    Print_FuncLine;
    print(wo);

    //去除重复元素
    //把不重复元素从前往后依次排列,并返回不重复区域之后第一个位置的迭代器
    std::vector<std::string>::iterator end_unique = unique(wo.begin(), wo.end());
    //删除掉不重复区域之后的元素
    wo.erase(end_unique, wo.end());

    cout << "去重后" << endl;
    Print_FuncLine;
    print(wo);
}

void biggies(vector<string> &wo, size_t sz)
{
    //按字典排序,并删除重复元素
    elimDups(wo);

    //按长度排序,长度相同的维持字典序
    //stable_sort(wo.begin(), wo.end(), isShorter);
    stable_sort(wo.begin(), wo.end(),
                [](const string &s1, const string &s2) {
                    return s1.size() < s2.size();
                });

    cout << "去重后 + 按字符串的长度排序,后" << endl;
    Print_FuncLine;
    print(wo);

    //find_if()对输入序列中的每个元素调用给定的这个谓词
    vector<string>::iterator bigitr = find_if(wo.begin(), wo.end(),
                                              [sz](const string &w) {
                                                  return w.size() >= sz;
                                              });
    Print_FuncLine;
    for_each(bigitr, wo.end(),
             [](const string &s) {
                 cout << s << " ";
             });
    cout << endl
         << endl;

    wo.erase(wo.begin(), bigitr);

    cout << "去重后 + 按字符串的长度排序,后,且大于指定长度的字符串" << endl;
    Print_FuncLine;
    print(wo);
}
int main()
{
    vector<string> words{"the", "quick", "red", "fox", "jumps",
                         "over", "the", "slow", "red", "turtle",
                         "abcdef", "abcdef", "abcdefg", "abcdefg"};
    biggies(words, 4);

    return 0;
}
[root@lwh testcpp]# ./test4.out 
排序前
elimDups 28
size: 14
the quick red fox jumps over the slow red turtle abcdef abcdef abcdefg abcdefg 

排序后
elimDups 35
size: 14
abcdef abcdef abcdefg abcdefg fox jumps over quick red red slow the the turtle 

去重后
elimDups 45
size: 10
abcdef abcdefg fox jumps over quick red slow the turtle 

去重后 + 按字符串的长度排序,后
biggies 62
size: 10
fox red the over slow jumps quick abcdef turtle abcdefg 

biggies 70
over slow jumps quick abcdef turtle abcdefg 

去重后 + 按字符串的长度排序,后,且大于指定长度的字符串
biggies 81
size: 7
over slow jumps quick abcdef turtle abcdefg 

[root@lwh testcpp]# 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值