C++之lambda表达式

在介绍C++ lambda表达式之前,我们先了解下谓词的概念

谓词

在C++中,谓词是一种可调用对象(函数、函数对象或Lambda表达式),它返回一个布尔值,用于表示某种条件是否成立。谓词通常用于标准库算法的参数中,例如std::sort、std::find_if等,以确定元素是否符合某个条件。

谓词可以分为一元谓词和多元谓词,取决于它们接受的参数数量。

一元谓词(Unary Predicate):

一元谓词接受一个参数。例如,一个一元谓词可以是一个函数,它接受一个参数并返回一个布尔值,或者是一个Lambda表达式。

// 一元谓词:检查一个整数是否为正数
bool isPositive(int x) {
    return x > 0;
}

// 使用一元谓词的例子
std::vector<int> numbers = {1, -2, 3, -4, 5};
auto it = std::find_if(numbers.begin(), numbers.end(), isPositive);

或者使用Lambda表达式:

std::vector<int> numbers = {1, -2, 3, -4, 5};
auto it = std::find_if(numbers.begin(), numbers.end(), [](int x) { return x > 0; });

多元谓词(N-ary Predicate):

我们先给出一个二元谓词(Binary Preficate)的例子。
使用 std::sort 对一个包含自定义结构体(Persion)的vector进行排序

#include <algorithm>
#include <iostream>
#include <vector>

struct Person {
    std::string name;
    int age;

    Person(const std::string& n, int a) : name(n), age(a) {}
};

int main() {
    std::vector<Person> people = {
        {"Alice", 30},
        {"Bob", 25},
        {"Charlie", 35},
        {"David", 28}
    };

    // 使用多元谓词的例子:按照年龄升序排序
    std::sort(people.begin(), people.end(), [](const Person& p1, const Person& p2) {
        return p1.age < p2.age;
    });

    // 输出排序结果
    for (const auto& person : people) {
        std::cout << person.name << " - " << person.age << " years old" << std::endl;
    }

    return 0;
}

在这个例子中,我们使用了 std::sort 和一个多元谓词Lambda表达式,该谓词按照 Person 结构体的 age 成员进行升序排序。Lambda表达式接受两个参数,即两个 Person 对象,然后根据它们的年龄进行比较。

在C++中,Lambda表达式可以接受任意数量的参数,因此可以用于实现三元或更高元的谓词。一个三元谓词会接受三个参数,四元谓词会接受四个参数,以此类推。更多元的谓词用法类似,这里不再举例说明。

总结

无论是一元谓词还是多元谓词,它们都用于定义特定条件的可调用对象,以便在标准库算法或其他需要谓词的上下文中使用。这种灵活性使得C++中的算法更加通用,可以适应各种不同的条件。

有了谓词的概念,下面接着介绍Lambda表达式

Lambda表达式

Lambda表达式是C++11引入的一个强大特性,可以编写内联的匿名函数。以下是Lambda表达式的一些需要了解的知识和细节:

1. 基本语法:

Lambda表达式的基本语法包括捕获列表、参数列表、返回类型和函数体。例如:

[capture](parameters) -> return_type {
    // function_body
}

capture: 捕获列表,定义了 lambda 函数体外的变量如何在 lambda 内被使用。
parameters: 参数列表,和普通函数的参数列表一样。
return_type: 返回类型。在很多情况下,返回类型可以被编译器推断,因此可以省略。
function_body: 函数体,包含 lambda 函数的代码。

2. 捕获列表(Capture List):

  • [] : 不捕获任何外部变量
  • [=]:以值传递方式捕获所有外部变量。
  • [&]:以引用传递方式捕获所有外部变量。
  • [x, y]:以值传递方式捕获指定的变量。
  • [&x, &y]:以引用传递方式捕获指定的变量。
  • [=, &x]:混合值传递和引用传递方式捕获变量。

3. 参数列表:

Lambda表达式可以包含参数,与普通函数类似。例如:

[](int x, int y) { /* 函数体 */ }

4. 返回类型推导:

Lambda表达式的返回类型可以显式指定,也可以根据返回语句进行自动推导。例如:

显示指定:

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

自动推导:

[](int x, int y) { return x + y; }

5. Lambda表达式作为函数参数:

Lambda表达式可以作为函数的参数传递,通常用于算法和STL中的函数。例如:

std::for_each(vec.begin(), vec.end(), [](int x) { /* 函数体 */ });

6. mutable关键字:

如果Lambda表达式需要修改捕获的变量,需要使用mutable关键字。例如:

int x = 0;
auto lambda = [x]() mutable { ++x; };

7. 高级特性

  • 可变 Lambda: 使用关键字 mutable 允许您修改按值捕获的变量。
    如果Lambda表达式需要修改捕获的变量,需要使用mutable关键字。例如:

    int x = 0;
    auto lambda = [x]() mutable { ++x; };
    
  • 泛型 Lambda: 自 C++14 起,可以使用自动类型推断的参数,使得 lambda 可以类似模板函数那样工作。

    auto add= [](auto x, auto y) {
    	return x + y;
    };
    std::cout << add(5, 3) << std::endl;     // 输出整数 8
    std::cout << add(2.5, 3.5) << std::endl; // 输出浮点数 6.0
    

8. Lambda表达式的限制和注意事项:

Lambda表达式不能包含声明语句。
捕获列表和参数列表可以为空,但{}是必需的。

Lambda表达式使得C++中的函数式编程风格更加灵活和方便,同时提高了代码的可读性和可维护性。Lambda表达式通常在需要定义短小而具体的函数时非常有用,使得代码更加紧凑而不失可读性。

  • 14
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值