• 【C++基础】lambda表达式


    这个其实在QT中经常用到,但是之前自己学习的时候也是一知半解的,没有彻底的搞明白,在这里,做一个整理

    文章参考:Lambda表达式 | 爱编程的大丙

    lambda表达式定义了一个匿名函数,并且可以捕获一定范围内的变量。其语法形式归纳如下:

    [capture](params) opt -> ret {body;};

    capture是捕获列表,params是参数列表,opt是函数选项,ret是返回值类型,body是函数体。

    捕获列表[]: 捕获一定范围内的变量

    参数列表(): 和普通函数的参数列表一样,如果没有参数参数列表可以省略不写。

    opt 选项, 不需要可以省略
            mutable: 可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)

                            auto f2 = [=]()mutable {return a++; };     // ok,其中a是外部捕获的值
            exception: 指定函数抛出的异常,如抛出整数类型的异常,可以使用throw();

    返回值类型:在C++11中,lambda表达式的返回值是通过返回值后置语法来定义的。

    C++11中允许省略lambda表达式的返回值,一般情况下,不指定lambda表达式的返回值,编译器会根据return语句自动推导返回值的类型,但需要注意的是labmda表达式不能通过列表初始化自动推导出返回值类型。

    auto f1 = []()
    {
        return {1, 2};    // 基于列表初始化推导返回值,错误
    }

    函数体:函数的实现,这部分不能省略,但函数体可以为空。

    关于捕获列表:

    [] - 不捕捉任何变量
    [&] - 捕获外部作用域中所有变量, 并作为引用在函数体内使用 (按引用捕获)
    [=] - 捕获外部作用域中所有变量, 并作为副本在函数体内使用 (按值捕获),拷贝的副本在匿名函数体内部是只读的,不能修改,若修改则会报错,除非使用opt选项为mutable
    [=, &foo] - 按值捕获外部作用域中所有变量, 并按照引用捕获外部变量 foo
    [bar] - 按值捕获 bar 变量, 同时不捕获其他变量
    [&bar] - 按引用捕获 bar 变量, 同时不捕获其他变量
    [this] - 捕获当前类中的this指针,让lambda表达式拥有和当前类成员函数同样的访问权限
    如果已经使用了 & 或者 =, 默认添加此选项

    例如:

    1. #include
    2. #include
    3. using namespace std;
    4. class Test
    5. {
    6. public:
    7. void output(int x, int y)
    8. {
    9. auto x1 = [] {return m_number; }; // error
    10. auto x2 = [=] {return m_number + x + y; }; // ok
    11. auto x3 = [&] {return m_number + x + y; }; // ok
    12. auto x4 = [this] {return m_number; }; // ok
    13. auto x5 = [this] {return m_number + x + y; }; // error
    14. auto x6 = [this, x, y] {return m_number + x + y; }; // ok
    15. auto x7 = [this] {return m_number++; }; // ok
    16. int a = 10, b = 20;
    17. auto f1 = [] {return a; }; // error
    18. auto f2 = [&] {return a++; }; // ok
    19. auto f3 = [=] {return a; }; // ok
    20. auto f4 = [=] {return a++; }; // error
    21. auto f5 = [a] {return a + b; }; // error
    22. auto f6 = [a, &b] {return a + (b++); }; // ok
    23. auto f7 = [=, &b] {return a + (b++); }; // ok
    24. }
    25. int m_number = 100;
    26. };

     lambda表达式的本质

    lambda表达式的类型在C++11中会被看做是一个带operator()的类,即仿函数。
    按照C++标准,lambda表达式的operator()默认是const的,一个const成员函数是无法修改成员变量值的。

    因为lambda表达式在C++中会被看做是一个仿函数,因此可以使用std::function和std::bind来存储和操作lambda表达式:

    1. #include
    2. #include
    3. using namespace std;
    4. int main(void)
    5. {
    6. // 包装可调用函数
    7. std::function<int(int)> f1 = [](int a) {return a; };
    8. // 绑定可调用函数
    9. std::function<int(int)> f2 = bind([](int a) {return a; }, placeholders::_1);
    10. // 函数调用
    11. cout << f1(100) << endl;
    12. cout << f2(200) << endl;
    13. return 0;
    14. }

    对于没有捕获任何变量的lambda表达式,还可以转换成一个普通的函数指针:

    1. using func_ptr = int(*)(int);
    2. // 没有捕获任何外部变量的匿名函数
    3. func_ptr f = [](int a)
    4. {
    5. return a;
    6. };
    7. // 函数调用
    8. f(1314);

  • 相关阅读:
    【JavaScript高级】01-this的指向
    WPF程序给按钮增加不同状态的图片
    顶级手机数据恢复软件 [2024 更新]
    TensorFlow C++编译及推理
    【Hadoop】二、Hadoop MapReduce与Hadoop YARN
    STM32 Flash
    【面试题】面试官:请你实现一个深拷贝,那如果是正则/set/函数怎么拷贝?
    servlet开发-通过Tomcat部署一个简单的webapp
    RBD块存储设备的扩容以及缩容操作(六)
    base64转file类型,并且作为参数发起axios/xhr请求(已封装好)
  • 原文地址:https://blog.csdn.net/weixin_42809675/article/details/132841926