【C++11】lambda表达式 的定义、性质和用法

定义

Lambda表达式是C++11引入的一种函数对象的匿名表示方法。它可以用于定义轻量级的、临时的、内联的函数对象,通常用于函数式编程的场景。

语法结构

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

lambda表达式书写格式:[capture-list] (parameters) mutable -> return-type {
	// 函数体 - statement
}

ambda表达式各部分说明:

  • [capture-list] : 捕捉列表,该列表总是出现在lambda函数的开始位置,编译器根据[]来判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda函数使用。
  • (parameters):参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以连同()一起省略
  • mutable:默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性。使用该修饰符时,参数列表不可省略(即使参数为空)。
  • ->returntype:返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推导。
  • {}中是Lambda表达式的函数体,包含了实际要执行的代码逻辑

需要注意的是:

在lambda函数定义中,参数列表返回值类型都是可选部分,而捕捉列表函数体可以为。因此C++11中最简单的lambda函数为:[]{}; 该lambda函数不能做任何事情

【C++11】lambda表达式 的定义、性质和用法_第1张图片

关于 捕获列表

捕捉列表描述了上下文中那些数据可以被lambda使用,以及使用的方式传值还是传引用

  • [var]:表示值传递方式捕捉变量var
  • [=]:表示值传递方式捕获所有父作用域中的变量(包括this)
  • [&var]:表示引用传递捕捉变量var
  • [&]:表示引用传递捕捉所有父作用域中的变量(包括this)
  • [this]:表示值传递方式捕捉当前的this指针

性质

  1. 父作用域指包含lambda函数的语句块
  2. 语法上捕捉列表可由多个捕捉项组成,并以逗号分割。例如:

[=, &a, &b]:以引用传递的方式捕捉变量a和b,值传递方式捕捉其他所有变量 [&,a, this]:值传递方式捕捉变量a和this,引用方式捕捉其他变量

  1. 捕捉列表不允许变量重复传递,否则就会导致编译错误。例如:

比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重复

  1. 在块作用域以外的lambda函数捕捉列表必须为空。
  2. 块作用域中的lambda函数仅能捕捉父作用域中局部变量捕捉任何非此作用域或者非局部变量都会导致编译报错
  3. lambda表达式之间不能相互赋值,即使看起来类型相同

原因:Lambda表达式是一种匿名函数,它生成的函数对象是一个闭包。每个Lambda表达式都有其自己的类型,并且不同的Lambda表达式具有不同的类型。因此,Lambda表达式之间不能直接相互赋值。

可以使用 函数指针 / std::function 进行函数赋值

// 函数指针实现 函数赋值
void f1() {
    std::cout << "hello" << std::endl;
}

void f2() {
    std::cout << "hello" << std::endl;
}

int main()
{
    void (*pf)();
    pf = f1; // 将函数指针pf指向f1
    pf();    // 调用f1函数

    pf = f2; // 将函数指针pf指向f2
    pf();    // 调用f2函数

    return 0;
}

常见用法

1. 作为函数对象传递:

Lambda表达式可以作为参数传递给需要函数对象作为参数的函数,例如:

// 函数接受一个函数对象作为参数
void process(std::function<void(int)> func) {
    // ...
}

// 调用时使用Lambda表达式作为参数
process([](int x) {
    // Lambda表达式的逻辑
    // ...
});

2. 在算法中使用:

Lambda表达式可以与标准库中的算法一起使用,用于指定算法的操作行为,例如:

std::vector<int> nums = {1, 2, 3, 4, 5};

// 使用Lambda表达式作为排序准则
std::sort(nums.begin(), nums.end(), [](int a, int b) {
    return a < b;
});

// 使用Lambda表达式作为条件判断
auto it = std::find_if(nums.begin(), nums.end(), [](int num) {
    return num > 3;
});

3. 自定义比较器:

Lambda表达式可以用来定义自定义的比较器,例如在容器排序或二叉搜索树中使用,例如:

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

std::vector<Person> people = {{"Alice", 25}, {"Bob", 30}, {"Charlie", 20}};

// 使用Lambda表达式定义自定义比较器
std::sort(people.begin(), people.end(), [](const Person& p1, const Person& p2) {
    return p1.age < p2.age;
});

4. 异步编程:

Lambda表达式可以用于异步编程,例如与std::async一起使用,创建异步任务,例如:

auto future = std::async([]() {
    // 异步任务的逻辑
    // ...
    return result;
});

// 获取异步任务的结果
auto result = future.get();

你可能感兴趣的:(C++进阶,c++,java,开发语言)