C++速通Lambda表达式

目录

lambda

1、什么是lambda

lambda 表达式 是 C++11 引入的一种语法,让你可以在代码中直接定义一个"匿名函数",不需要写函数名。

示例demo

cpp 复制代码
#include <iostream>
#include <cstdio>
int main()
{
    auto add = [](int a, int b) -> int
    {
        return a + b;
    };

    printf("add : %d\n", add(3, 4));
    return 0;
}

2、lambda的结构

cpp 复制代码
[capture](parameters) mutable noexcept -> return_type {
// 函数体
}

capture     :  捕获列表
parameters  : 参数列表
mutable     : 可变规则
noexcept    : 异常说明
return_type : 指定返回类型
{}          :  函数体
2.1、捕获列表(capture)

捕获列表一共有下述五种类型

捕获方式 写法 含义
值捕获 [x] 拷贝外部变量 x 的值
引用捕获 [&x] 按引用使用外部变量 x
全部值捕获 [=] 拷贝父作用域所有外部变量
全部引用捕获 [&] 引用父作用域所有外部变量
混合捕获 [=, &y] / [&, x] 大部分按某种方式捕获,个别特殊指定

值捕获[x]

cpp 复制代码
#include <iostream>
#include <cstdio>
int main()
{
    int a = 1;
    auto GetPrama = [a](){
        printf("a : %d\n", a);
    };

    GetPrama();
    return 0;
}

1、此方式不能在lambda表达式内部改变捕获变量的数值, 也可以理解为传入的参数a是const类型的变量,因此 无法在函数体内修改

2、此方式还可以捕获this

cpp 复制代码
#include <iostream>
#include <cstdio>

class TestLambda
{
public:
    TestLambda() = default;
    ~TestLambda() = default;
    TestLambda(const TestLambda &other) = delete;
    TestLambda& operator=(const TestLambda &other) = delete;
    TestLambda(TestLambda &&other) = delete;
    TestLambda& operator=(TestLambda &&other) = delete;

public:
    void LambadFunc()
    {
        auto func = [this](){
            this->Print();
        };

        func();
    }

private:
    void Print()
    {
        printf("i am : %s\n", __FUNCTION__);
    }
};

int main()
{
    TestLambda t;
    t.LambadFunc();
    return 0;
}

3、如果**[]**中什么也不写,则不捕获任何东西。

引用捕获[&x]

值捕获 的例子中我们的a无法在lambda的函数体中改变,如使用引用捕获则可以改变

cpp 复制代码
#include <iostream>
#include <cstdio>
int main()
{
    int a = 1;
    auto GetPrama = [&a](){
        a = 6;
        return a;
    };

    printf("a : %d\n", GetPrama());
    return 0;
}

ps:此方式也适用于引用捕获this

全部值捕获[=]

cpp 复制代码
#include <iostream>
#include <cstdio>
int main()
{
    int a = 1, b = 2, c = 3;
    auto GetPrama = [=]()
    {
        printf("a : %d, b : %d, c : %d\n", a, b, c);
    };
    GetPrama();
    return 0;
}

全部引用捕获[&]

cpp 复制代码
#include <iostream>
#include <cstdio>
#include <functional>
int main()
{
    int a = 1, b = 2, c = 3;
    std::function<void(void)> GetPrama = [&]()
    {
        a = 6;
        b = 6;
        c = 6;
    };
    GetPrama();
    printf("a : %d, b : %d, c : %d\n", a, b, c);
    return 0;
}

混合捕获

cpp 复制代码
#include <iostream>
#include <cstdio>
#include <functional>
int main()
{
    int a = 1, b = 2, c = 3;
    std::function<void(void)> GetPrama1 = [&, b]() // 全部引用捕获但是b除外, b是值捕获
    {
        a = 6;
        // b = 6; 唯独b是值捕获,因此无法在lambda的函数体中修改。
        c = 6;
    };
    GetPrama1();
    printf("a : %d, b : %d, c : %d\n", a, b, c);

    // std::function<void(void)> GetPrama2 = [b, &]() //<---b说明是值捕获b,然后&是全部引用捕获。
    // {                                              // 混合捕获只支持这两种模式 [=, &y, &z ....] [&, x, y, z ....]
    //     a = 6;
    //     b = 6; 
    //     c = 6;
    // };

    std::function<void(void)> GetPrama3 = [=, &b, &c]() // 全部引用捕获但是b除外, b是值捕获
    {
        // a = 6; 唯独a是值捕获,因此无法在lambda的函数体中修改。
        b = 8; 
        c = 8;
    };
    GetPrama3();
    printf("a : %d, b : %d, c : %d\n", a, b, c);
    return 0;
}
2.2、参数列表(parameters)

参数列表很好理解,就当函数参数一样定义就行

cpp 复制代码
#include <iostream>
#include <cstdio>
#include <functional>
int main()
{
    int a = 1, b = 2, c = 3;
    auto GetPrama1 = [a, b](int &x, int &y)
    {
        x = a;
        y = b;
    };
    int x, y;
    GetPrama1(x, y);
    printf("x : %d, y : %d\n", x, y);
    return 0;
}
2.3、可变规则(mutable)

上面我们说了值捕获无法修改捕获对象的数值,但是使用mutable可以强制捕获,让其在lambda的函数体中可以被改变,但是函数体以外捕获对象的数值是不变得。

cpp 复制代码
#include <iostream>
#include <cstdio>
#include <functional>
int main()
{
    int a = 1, b = 2, c = 3;
    auto GetPrama1 = [a]() mutable
    {
        a = 6;
        printf("GetPrama1 a : %d\n", a);
    };
    GetPrama1();
    printf("main a : %d\n", a); //原本a的数不会被改变。
    return 0;
}
2.4、 异常说明(noexcept)

这个一般不咋用到,简单点说如果你认为你的函数体内不会抛出异常,你就可以带上这个参数。

cpp 复制代码
#include <iostream>
#include <cstdio>
#include <functional>
int main()
{
    int a = 1;
    auto GetPrama1 = [a]() mutable noexcept
    {
        a = 6;
    };
    GetPrama1();
    printf("a : %d\n", a);
    return 0;
}
2.5、指定返回类型(return_type)

lambda默认推导出返回值类型,也可以显式指定返回值的类型。

cpp 复制代码
#include <iostream>
#include <cstdio>
#include <functional>
int main()
{
    auto GetPrama = []() mutable noexcept -> double
    {
        int a = 6, b = 2;
        return static_cast<double>(a/b);
    };
    printf("val : %f\n", GetPrama());
    return 0;
}

结语

感谢您的阅读,如有问题可以私信或评论区交流。

^ _ ^

相关推荐
源码_V_saaskw3 小时前
JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码小程序+公众号+h5
java·开发语言·微信小程序·小程序
C嘎嘎嵌入式开发3 小时前
(20)100天python从入门到拿捏《JSON 数据解析》
开发语言·python·json
源码哥_博纳软云3 小时前
JAVA同城预约服务家政服务美容美发洗车保洁搬家维修家装系统源码小程序+公众号+h5
java·开发语言·微信小程序·小程序
snow@li3 小时前
d3.js:学习积累
开发语言·前端·javascript
编程岁月3 小时前
java面试-0203-java集合并发修改异常、快速/安全失败原理、解决方法?
java·开发语言·面试
CoderCodingNo4 小时前
【GESP】C++五级考试大纲知识点梳理, (3-4) 链表-双向循环链表
开发语言·c++·链表
llz_1124 小时前
第五周作业(JavaScript)
开发语言·前端·javascript
colus_SEU4 小时前
【编译原理笔记】2.1 Programming Language Basics
c++·算法·编译原理
W.Y.B.G4 小时前
JavaScript 计算闰年方法
开发语言·前端·javascript