C++中的Lambda表达式详解

C++中的Lambda表达式详解

简介:
Lambda表达式(又称Lambda函数,英文原文是Lambda Expression),是C++11的新特性中非常实用的一个。

按照cppreference的官方中文解释,

构造一个闭包:能在作用域内捕获变量一个的匿名函数对象。

一个常见的Lambda表达式的结构如下(省略了mutable、exception、attribute和-> ret):
[ 捕获 ] ( 参数列表 ) { 函数体 }

例如:

 [](int a, int b) -> int { return a + b; };

除了[]是Lambda表达式特有的,后面的参数列表、函数体是和普通命名函数一样的。那捕获是什么意思该怎么写呢?

[&]表示以引用形式捕获当前作用域的全部自动储存持续性变量
[=]表示以传值形式捕获当前作用域的全部自动储存持续性变量
[a, &b]以传值形式捕获变量a,以引用形式捕获变量b
[a, &]以传值形式捕获变量a,以引用形式捕获当前作用域其它的自动储存持续性变量
[this]以传值形式捕获this指针
[]什么也不捕获

  // 定义一个简单的lambda表达式
    auto basicLamda = [] {cout << "hello world!" << endl; };
    basicLamda();  // 调用
    // 如果需要参数,那么就要像函数那样,放在圆括号里面,如果有返回值,返回类型要放在->后面,即拖尾返回类型
    // 当然你也可以忽略返回类型,lambda会帮你自动推断出返回类型
    auto add = [](int a, int b) -> int {return a + b; };
    int result = add(4, 5);
    cout << "result = " << result << endl;
    // 自动推断出返回类型
    auto multiply = [](int a, int b) {return a * b; };
    int result1 = multiply(5, 6);
    cout << "result1 = " << result1 << endl;

对于[=]或[&]的形式,lambda表达式可以直接使用this指针。但是,对于[]的形式,如果要使用this指针,必须显式传入:this { this->someFunc(); }();

    class Test{
    public:
        void hello(){
            cout << "test hello!\n";
        };
        void lambda(){
            auto fun = [this]{ // 捕获了 this 指针
            this->hello(); 
            }; // 这里 this 调用的就是 class Test 的对象了
            fun();
        }
    };

所谓传值(value)还是引用(reference)和命名函数中一样,引用传递的参数在Lambda表达式的函数体中被修改后,原作用域的变量也会发生变化,而传值的变量则会被作为只读变量供Lambda表达式函数体来使用,Lambda表达式的函数体无法修改该变量(加上mutable关键词可以修改,但是修改的结果不会影响到原作用域)。

#include 
#include 
#include 
 
using namespace std;
 
int main ()
{
        int a = 10, b = 10;
        function<void (void)> func1 = [a] () mutable { cout << ++a << endl; };
        function<void (void)> func2 = [&b] () { cout << ++b << endl; };
 
        func1();
        func2();
        cout << "a: " << a << "\nb: " << b << endl;
 
        return 0;
}

上述代码的输出:

11
11
a: 10
b: 11

可以看到,虽然有mutable关键词,在func1函数体内部也被修改了,但是在原作用域(即main中),a并没有被修改,因为a是通过传值捕获的变量。而b成功被修改了,因为b是引用捕获的。如果去掉mutable关键词,这段代码在编译时就会报错,因为默认传值捕获的变量是只读的(相当于常量),不可以被修改。

lamdba表达式这部分的内容应该不难,编程的学习,其实还是如同英语的学习都一样,了解语法后,然后多练习debug 加深理解。同时对照一些必要的参考手册,教材。本篇内容的参考可以阅读:[Lambda函数],(https://zh.cppreference.com/w/cpp/language/lambda)

你可能感兴趣的:(Qt基础,c++,lambda)