C++11特性:Lambda表达式

什么是Lambda表达式

Lambda 表达式,也称为匿名函数,允许定义一个没有名称的函数表达式。Lambda 表达式特别适用于编写简短的回调函数或实现简单的操作,而不需要正式定义一个函数。

在这里说一下什么是回调函数

回调函数是一个通过参数传递给另一个函数,并在那个函数内部被执行的函数。这种机制允许程序在特定的时刻或条件下,自动调用某个函数。回调函数是一种在编程中广泛使用的概念,尤其在异步编程、事件监听和某些设计模式中特别常见。

一般使用函数指针作为参数来调用回调函数实现。

回调函数相比于直接调用函数主要有以下优点

解耦:

直接调用创建了明确的依赖关系。通常意味着较强的耦合性。一个函数直接依赖于它所调用的函数。在大型或复杂的系统中,这种紧密耦合可能导致代码难以理解和修改。

回调函数通过提供一个中间层(通常是通过接口或函数指针/引用)来减少依赖,从而实现解耦。调用方不需要知道回调的具体实现,只需知道它符合预期的签名和行为。这种方式使得不同的组件或模块能够更独立地发展和变化。

异步处理:

直接调用在大多数情况下是同步的,意味着调用方在被调用的函数返回之前会被阻塞。

回调函数经常用于异步编程。在这种模式下,一个操作可以启动一个任务,并立即返回,不会阻塞调用方。当任务完成时,通过回调函数通知调用方。这对于提高应用程序的响应性和性能非常重要,尤其是在处理I/O、网络请求等长时间运行的操作时。

举个例子,用Lambda 表达式写一个回调函数可以是在STL中的排序方法的第三个参数。

    std::sort(numbers.begin(), numbers.end(), [](int a, int b) {
        return a < b; // 升序排序
    });

在C++11以前,需要自定义一个函数,并将函数名作为第三个参数在sort执行时调用来确定排序规则。如果使用Lambda 表达式的话不但简化了代码也减少了函数调用的一些开销。

Lambda表达式的基本格式

[] () mutable ->type {};

其中:

1.【】表示捕获列表

静态/全局变量可以直接捕获可不写【】
[=]捕获非静态局部变量,值传递
[&]捕获非静态局部变量,引用传递
[val] ,捕获val变量,值传递
[&val] 捕获val的引用传递
[this]捕获this指针

注意:

不可写[=,val],这样写就重复了,不能这么写,[&,&val]也是一样

2.()表示参数列表 参数可以用auto。匿名函数没有参数可以不写

3.(mutable)表示是否为常函数,不加mutable默认为常函数,无法修改函数内部的变量。加上mutable可以修改函数内部的变量了。只有mutable和引用捕获变量时才可以修改真正修改捕获的变量。

4. ->type表示返回值类型,可以省略lambda表达式的返回值定义,返回值可以使用auto关键字来接

#include 
using namespace std;
int main() {
    auto lambda = [](auto x, auto y) -> auto { return x + y; }; 
    cout << lambda(5, 6) << endl;
    cout << lambda(3.14, 2.86) << endl;
    cout << sizeof(lambda(5, 6)) << endl; 
    cout << sizeof(lambda(3.14, 2.86)) <

C++11特性:Lambda表达式_第1张图片

输出结果分别是 11 6 4 8

5. {};表示函数体,里面是匿名函数的内部实现。

与function和bind的关系

function是一个函数包装器(function wrapper),它可以存储、调用或引用任何类型的可调用对象,包括普通函数、Lambda表达式、函数对象以及成员函数指针。

Lambda表达式可以被赋给一个function类型的变量。这使得Lambda表达式更加灵活,因为你可以在代码中传递function变量,而不必担心具体的可调用实体类型。

#include 
#include 

int main() {
    std::function add = [](int a, int b) -> int {
        return a + b;
    };

    std::cout << add(2, 3) << std::endl; // 输出5
}

bind是一个函数适配器,它可以将可调用对象与其参数一起绑定,部分或全部,返回一个新的可调用对象。新的可调用对象可以被调用时无需(或只需部分)提供那些已经被绑定的参数。

尽管Lambda表达式本身就很灵活,能够捕获变量并模仿bind的行为,但在某些情况下,结合使用bind和Lambda表达式可以提供额外的灵活性。例如,当你需要改变Lambda表达式接收参数的顺序,或者只是想要预先填充某些参数时。

#include 
#include 

int main() {
    auto add = [](int a, int b) -> int {
        return a + b;
    };

    auto add_to_3 = std::bind(add, std::placeholders::_1, 3);
    std::cout << add_to_3(2) << std::endl; // 输出5
}

在这里面,就将表达式的其中一个参数设为默认值3,并返回了一个新的表达式。、

不过这两个关键字我用的还真的不太多,后面还需要继续学习。

你可能感兴趣的:(开发语言)