C++——Lambda表达式

C++——Lambda表达式

Lambda表达式介绍

Lambda 表达式是 C++11 引入的一种匿名函数的方式,它允许你在需要函数的地方内联地定义函数,而无需单独命名函数

Lambda 表达式的基本语法如下:

[capture clause](parameters) -> return_type {
// 函数体
// 可以使用捕获列表中的变量
return expression; // 可选的返回语句
}

Lambda 表达式由以下部分组成:

捕获列表(Capture clause):用于捕获外部变量,在 Lambda 表达式中可以访问这些变量。捕获列表可以为空,也可以包含变量列表 [var1, var2, …] 。

参数列表(Parameters):与普通函数的参数列表类似,可以为空或包含参数列表 (param1,param2, …) 。

返回类型(Return type):Lambda 表达式可以自动推断返回类型auto,也可以显式指定返回类型 -> return_type 。如果函数体只有一条返回语句,可以省略返回类型。

函数体(Body):Lambda 表达式的函数体,包含需要执行的代码。

Lambda 表达式最简单的案例是在需要一个小型函数或临时函数时直接使用它。以下是一个非常简单的例子,其中使用 Lambda 表达式来定义一个加法操作,并立即使用它来计算两个数的和。

使用 Lambda 表达式进行加法

#include <iostream>

using namespace std;

/*[capture clause](parameters) -> return_type {
// 函数体
// 可以使用捕获列表中的变量
return expression; // 可选的返回语句
}

int add(int x,int y)
{
   return x+y;
}
*/

int main()
{
    int x=20;
    int y=30;

    auto add=[](int x,int y)->int
    {
        return x+y;
    };

    int ret=add(x,y);
    cout<<ret<<endl;
    return 0;
}
#include <iostream>
int main() {
    // 定义一个简单的 Lambda 表达式进行加法
    auto add = [](int a, int b) {
        return a + b;
    };
    // 使用 Lambda 表达式计算两个数的和
    int sum = add(10, 20);
    std::cout << "Sum is: " << sum << std::endl;
    return 0;
}

在这个例子中:

  • 我们定义了一个名为 add 的 Lambda 表达式,它接受两个整数参数,并返回它们的和。
  • 然后,我们使用这个 Lambda 表达式来计算两个数字(10 和 20)的和,并将结果存储在变量 sum中。
  • 最后,我们打印出这个和。

这个例子展示了 Lambda 表达式的基本用法:作为一种简洁而快速的方式来定义小型函数。

我们可以写一个例子,其中使用一个函数来找出两个数中的较大数,这个函数将接受一个 lambda 函数

作为回调来比较这两个数。Lambda 函数将直接在函数调用时定义,完全是匿名的。

使用匿名 Lambda 函数来返回两个数中的较大数

回忆回调函数

#include <iostream>
// 函数,接受两个整数和一个比较的 lambda 函数
bool myCompare(int a, int b){
    return a > b;
}
int getMax(int a, int b, bool(*compare)(int, int)) {
    if (compare(a, b)) {
        return a;
    } else {
        return b;
    }
}
int main() {
    int x = 10;
    int y = 20;
    // 回调函数
    int max = getMax(x, y, myCompare);
    std::cout << "The larger number is: " << max << std::endl;
    return 0;
}

示例

#include <iostream>
// 函数,接受两个整数和一个比较的 lambda 函数
int getMax(int a, int b, bool(*compare)(int, int)) {
    if (compare(a, b)) {
        return a;
    } else {
        return b;
    }
}
int main() {
    int x = 10;
    int y = 20;
    // 直接在函数调用中定义匿名 lambda 函数
    int max = getMax(x, y, [](int a, int b) -> bool {
        return a > b;
    });
    std::cout << "The larger number is: " << max << std::endl;
    return 0;
}

在这个例子中:

getMax 函数接受两个整数 a 和 b ,以及一个比较函数 compare 。这个比较函数是一个指向函数的指针,它接受两个整数并返回一个布尔值。

在 main 函数中,我们调用 getMax ,并直接在调用点定义了一个匿名的 lambda 函数。这个lambda 函数接受两个整数并返回一个表示第一个整数是否大于第二个整数的布尔值。

这个 lambda 函数在 getMax 中被用作比较两个数的逻辑。根据 lambda 函数的返回值, getMax返回较大的数。

这个例子展示了如何直接在函数调用中使用匿名 lambda 函数,使代码更加简洁和直接。这种方法在需要临时函数逻辑的场合非常有用,尤其是在比较、条件检查或小型回调中

使用带参数捕获的 Lambda 表达式

在 Lambda 表达式中,参数捕获是指 Lambda 表达式从其定义的上下文中捕获变量的能力。这使得Lambda 可以使用并操作在其外部定义的变量。捕获可以按值(拷贝)或按引用进行。

示例1

#include <iostream>

using namespace std;

int main()
{
    int x=10;
    int y=20;
    int z=30;

    auto add=[x,y]()->int{
          //x=15;
          return x+y; //这种方式捕获,不能修改变量的值,可读
    };
    int ret=add();
    cout<<ret<<endl;

    auto mul=[=]()->int{
        //x=15;
        return x*y*z; //这种方式能捕获所有变量,不能修改变量的值,可读
    };
    ret=mul();
    cout<<ret<<endl;

    //用引用的方式捕获变量,类似指针,地址访问
    auto modiflyAndmul=[&]()->int{
          x=15;         //这种方式捕获,可以修改变量的值,可读可写
          return x*y*z;
    };
    ret=modiflyAndmul();
    cout<<ret<<endl;
    cout<<"x="<<x<<endl;
    return 0;
}

示例2

#include <iostream>
int main() {
    int x = 10;
    int y = 20;
    // 捕获 x 和 y 以便在 Lambda 内部使用
    // 这里的捕获列表 [x, y] 表示 x 和 y 被按值捕获
    auto sum = [x, y]() {
        // x++;
        // y++; 按值捕获,关注的是值本身,无法修改
        return x + y;
    };
    std::cout << "Sum is: " << sum() << std::endl;
    std::cout << "x is now: " << x << ", y is now: " << y << std::endl;
    // 捕获所有外部变量按值捕获(拷贝)
    int z = 30;
    auto multiply = [=]() {
        // x++;
        // y++; 按值捕获,关注的是值本身,无法修改
        return x * y * z;
    };
    count << x << "," << y << endl;
    std::cout << "Product is: " << multiply() << std::endl;
    std::cout << "x is now: " << x << ", y is now: " << y << std::endl;
    // 捕获所有外部变量按引用捕获
    auto modifyAndSum = [&]() {
        x = 15; // 修改 x 的实际值
        y = 25; // 修改 y 的实际值, 引用捕获可以修改
        return x + y;
    };
    std::cout << "Modified Sum is: " << modifyAndSum() << std::endl;
    std::cout << "x is now: " << x << ", y is now: " << y << std::endl;
    return 0;
}

在这个例子中:

第一个 Lambda 表达式 sum 按值捕获了 x 和 y (即它们的副本)。这意味着 sum 内的 x 和 y是在 Lambda 定义时的值的拷贝。

第二个 Lambda 表达式 multiply 使用 [=] 捕获列表,这表示它按值捕获所有外部变量。

第三个 Lambda 表达式 modifyAndSum 使用 [&] 捕获列表,这表示它按引用捕获所有外部变量。

因此,它可以修改 x 和 y 的原始值。

这个示例展示了如何使用不同类型的捕获列表(按值和按引用)来控制 Lambda 表达式对外部变量的访问和修改。按值捕获是安全的,但不允许修改原始变量,而按引用捕获允许修改原始变量,但需要注意引用的有效性和生命周期问题。

Lambda 函数和内联函数在 C++ 中的相似之处和区别:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 [&] 捕获列表,这表示它按引用捕获所有外部变量。

因此,它可以修改 x 和 y 的原始值。

这个示例展示了如何使用不同类型的捕获列表(按值和按引用)来控制 Lambda 表达式对外部变量的访问和修改。按值捕获是安全的,但不允许修改原始变量,而按引用捕获允许修改原始变量,但需要注意引用的有效性和生命周期问题。

Lambda 函数和内联函数在 C++ 中的相似之处和区别:[外链图片转存中…(img-07B1L5fs-1706802245228)]

请注意,虽然 Lambda 函数和内联函数在某些方面有相似之处,如它们都可以被编译器优化以减少调用开销,但它们在设计和用途上有明显的不同。Lambda 函数的核心优势在于它们的匿名性和对外部变量的捕获能力,而内联函数则主要关注于提高小型函数的性能。

  • 24
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Lambda表达式C++11引入的一种函数对象,可以在需要函数对象的地方使用,比如作为函数参数、返回值等。Lambda表达式的语法形式如下: ``` [capture list](parameters) mutable exception -> return type { // function body } ``` 其中,`capture list` 表示捕获列表,用于捕获外部变量。`parameters` 表示函数参数列表,`mutable` 用于表示是否可以修改值传递的变量,`exception` 是异常列表,`return type` 表示返回类型,`function body` 则是函数体。 在Lambda表达式中,可以通过 `[this]` 捕获当前对象的指针,即 `this` 指针,可以方便地访问当前对象的成员变量和成员函数。例如: ``` class MyClass { public: void foo() { int x = 1; auto lambda = [this, x]() mutable { this->m_member_var += x; this->m_member_function(); x++; }; lambda(); } private: int m_member_var; void m_member_function(); }; ``` 在上面的例子中,Lambda表达式通过 `[this, x]` 捕获了当前对象的指针和 `foo()` 函数中定义的变量 `x`。在 Lambda 表达式中可以通过 `this->m_member_var` 和 `this->m_member_function()` 访问当前对象的成员变量和成员函数。由于 `x` 是值传递的,所以在 Lambda 表达式中需要使用 `mutable` 关键字使其可修改,可以通过 `x++` 修改变量的值。最后调用 `lambda()` 执行 Lambda 表达式。 需要注意的是,Lambda表达式捕获 `this` 指针时,需要保证当前对象是有效的,即不能在已经销毁的对象中访问成员变量和成员函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值