c++11新特性之Lambda表达式

写在前面

当谈到 C++11 新特性,Lambda 表达式是其中最重要且最受欢迎的功能之一。Lambda 表达式允许我们在需要函数对象的地方,以一种简洁、灵活且内联的方式定义一个短小的、即时的匿名函数。Lambda表达式通常用于简化代码、使代码更具可读性,并在需要时提供一个可定制的行为。

基本语法


[capture list](parameters) -> return_type
{
    // 函数体
}

capture list: 用于捕获外部变量,可以为空。通过捕获外部变量,Lambda函数可以访问在其定义位置范围内的变量。
parameters: 用于指定Lambda函数的参数列表,与普通函数的参数列表相似。
return_type: 用于指定Lambda函数的返回类型。可以使用C++11的类型推断机制来自动推断返回类型,也可以明确指定返回类型。
{}:包含Lambda函数的函数体,实现函数的具体逻辑

Lambda表达式的使用

举一些例子

#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
	int x = 10;
	auto add = [x](int a, int b) { return a + b + x; };
	cout << add(3, 5) << endl; // 输出:18
	return 0;
}

上述代码中使用lambda表达式定义了一个名为add的函数对象,这个add的作用就是将传进来的两个函数参数a,b相加再加上外部变量x的和,并返回。这里没有给出返回值类型,程序员易于发现(只有一个return的情况),C++11的类型推断机制可以自动推断返回类型。
你可能会想这和普通的函数没什么区别,函数嵌套也一直存在着我们的代码中,接下来介绍它经常被使用到的地方

在算法函数中

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
    vector<int> numbers = {5, 2, 10, 8, 3};

    // 使用Lambda表达式排序numbers,按照从小到大的顺序
    sort(numbers.begin(), numbers.end(), [](int a, int b) {
        return a < b;
    });

    // 使用Lambda表达式遍历numbers,输出每个元素的平方
    cout << "Squared numbers: ";
    for_each(numbers.begin(), numbers.end(), [](int num) {
        cout << num * num << " ";
    });
    cout << std::endl;

    // 使用Lambda表达式计算numbers中所有元素的和
    int sum = 0;
    for_each(numbers.begin(), numbers.end(), [&sum](int num) {
        sum += num;
    });

    cout << "Sum of numbers: " << sum << std::endl;

    return 0;
}

在上面的例子中,我们使用了三个Lambda表达式:

1、在sort函数中,使用Lambda表达式来指定排序规则,按照从小到大的顺序排序numbers容器。
2、在std::for_each函数中,使用Lambda表达式来遍历numbers容器,并输出每个元素的平方。
3、在第二次使用std::for_each函数中,使用Lambda表达式来计算numbers容器中所有元素的和,并通过捕获列表将变量sum引入Lambda函数内部,易于知道,变量前加&是进行引用传递,不加&是值传递,即传的外部变量的副本,不改变其本身的值。

Lambda表达式的优势在于它能够减少代码中的冗余,并且能够在需要临时函数时快速创建一个短小的函数逻辑。

STL或自定义容器的比较函数


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 定义一个结构体
struct Person {
    string name;
    int age;

    // 构造函数
    Person(const string& n, int a) : name(n), age(a) {}
};

int main() {
    // 使用lambda表达式来定义自定义的比较函数
    // 以Person结构体的age成员变量为排序依据,按照递减顺序排序
    std::sort(people.begin(), people.end(), [](const Person& a, const Person& b) {
        return a.age > b.age;
    });
    return 0;
}


在这个例子中,我们定义了一个名为Person的结构体,其中包含了姓名name和年龄age这两个成员变量。我们使用std::sort算法对people向量进行排序,并传递了一个lambda表达式作为比较函数。在lambda表达式中,我们通过a.age和b.age来访问结构体Person的年龄成员,然后按照年龄的递减顺序进行排序

接下来再来看一个使用lambda表达式自定义构造堆(priority_queue)

#include <iostream>
#include <queue>
using namespace std;
int main() {
    // 使用lambda表达式实现自定义的比较(最小堆,升序排列)
    auto compare = [](int a, int b) {
        return a > b; // 使用递减顺序,数值大的优先级高,和sort是反着的
    };

    priority_queue<int, std::vector<int>, decltype(compare)> minHeap(compare);

    minHeap.push(5);
    minHeap.push(2);
    minHeap.push(8);

    while (!minHeap.empty()) {
        cout << minHeap.top() << " ";
        minHeap.pop();
    }//输出为 2 5 8

    return 0;
}

注意:在构造priority_queue时,我们将lambda表达式compare的类型作为第三个模板参数,并在创建minHeap对象时传递了这个lambda表达式到构造函数。这样,minHeap就使用了我们自定义的比较函数,从而实现了相应的优先级规则。

注意事项

一、捕获列表

捕获列表(Capture List):Lambda函数可以捕获外部变量,即在函数体中访问Lambda函数定义处范围内的变量。捕获列表使用方括号[ ]来指定,可以为空表示不捕获任何变量。捕获列表有两种方式:

值捕获(Value Capture):捕获外部变量的副本。
[=]:表示捕获lambda表达式定义作用域所有的变量的副本。
引用捕获(Reference Capture):通过引用捕获外部变量,可以在Lambda函数中修改捕获的变量。
[&]:表示捕获lambda表达式定义作用域所有的变量的引用。

int x = 5;
auto lambda1 = [x]() { cout << x << endl; }; // 值捕获,x的值在Lambda函数中不可修改
auto lambda2 = [&x]() { cout << x << endl; }; // 引用捕获,x的值在Lambda函数中可修改

二、参数列表

参数列表(Parameters):与普通函数一样,Lambda函数可以接受参数。参数列表使用小括号()指定。可以为空,表示不接受任何参数。

auto add = [](int a, int b) { return a + b; };
cout << add(3, 2) << endl; // 输出:5

三、返回类型

返回类型(Return Type):Lambda函数可以自动推断返回类型,也可以显式指定返回类型。当函数体较复杂或有多个返回路径时,显式指定返回类型是推荐的做法。

auto square = [](int x) -> int { return x * x; };
cout << square(4) << endl; // 输出:16

四、Lambda作为函数对象

Lambda作为函数对象:Lambda函数本质上是一个函数对象,可以像普通函数对象一样传递给其他函数或作为返回值。

#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
// 函数接受一个Lambda函数并将其应用于容器中的每个元素
void process(vector<int>& data, const function<void(int)>& func) {
    for (int num : data) {
        func(num);
    }
}

int main() {
    vector<int> numbers = {1, 2, 3, 4, 5};

    // 使用Lambda函数作为参数调用process函数
    process(numbers, [](int x) { std::cout << x << " "; });
    // 输出:1 2 3 4 5

    return 0;
}

写在后面

Lambda表达式是C++11引入的重要特性,它为编写更简洁、灵活和高效的代码提供了方便的工具。在现代C++开发中,Lambda表达式广泛应用于标准库算法、并发编程、回调函数等场景。它的出现大大简化了代码编写,提升了C++语言的表达力和编程效率。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SWPU_才

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值