C++ Lambda表达式

auto is_small_size = [this, &cu, ker](const Contour &contour) -> bool {

这段代码是C++中的lambda表达式(匿名函数)。Lambda表达式是C++11引入的特性,用于定义匿名函数对象,可以直接在代码中使用。

Lambda 表达式,并结合生活场景和实际代码例子,让你彻底搞懂它是什么、怎么用、为什么好用

1、Lambda 是什么?

通俗比喻:Lambda 就像一个 “临时工”

  • 普通函数(如void foo())是正式员工,需要提前定义、长期存在。

  • Lambda 是临时工,随用随招,用完即走。你可以在需要的地方直接定义一个 Lambda,快速解决问题,不用专门写一个正式函数。

2、Lambda的语法结构

用一句话总结Lambda的语法:“抓点东西,拿点参数,干点活,返回结果。”
对应的代码结构:

[抓取变量] (参数) -> 返回值类型 { 干活的具体代码 }

拆解说明:

  • [抓取变量]:Lambda 需要用到外部的变量时,要在这里“抓取”(捕获)它们。

    • 比如 [x] 表示抓取变量 x 的值;[&y] 表示抓取变量 y 的引用。

  • (参数):和普通函数一样,输入参数。

  • -> 返回值类型(可选):告诉编译器返回什么类型,一般可以省略(编译器自动推导)。

  • { 具体代码 }:Lambda 具体要做的事情。

3、Lambda的核心:捕获变量

为什么重要:Lambda 可以“记住”外部的变量,这是它灵活的关键!
捕获方式

  • 值捕获 [x]:把外部的 x 复制一份给 Lambda 使用,外界的 x 变了,Lambda 里的 x 不变。

  • 引用捕获 [&x]:直接使用外部的 x,Lambda 内部修改 x 会影响外部的值。

  • 混合捕获 [=, &y]:默认按值捕获所有变量,但 y 按引用捕获。

  • 抓取全部 [=] 或 [&]:按值或引用捕获所有外部变量。

生活场景
你让临时工(Lambda)去搬砖,但需要告诉他用哪里的砖:

  • 值捕获:临时工自己带了一车砖(复制一份),和你的砖无关。

  • 引用捕获:临时工直接去你的砖厂搬砖,搬走一块就少一块。

4、Lambda的实际应用场景

场景1:快速排序

为什么用 Lambda:排序规则只用一次,没必要单独写个函数。

#include 
#include 

int main() {
    std::vector nums = {3, -1, 4, -2, 5};
    
    // 用 Lambda 定义排序规则
    std::sort(nums.begin(), nums.end(), 
              [](int a, int b) { 
                  return abs(a) < abs(b); 
              });
    
    // 排序后:-1, -2, 3, 4, 5
    return 0;
}

场景2:按钮点击事件

// 伪代码示例
Button btn;
int clickCount = 0;

// 用 Lambda 定义点击后的动作
btn.onClick([&clickCount]() {
    clickCount++;  // 捕获 clickCount 的引用,直接修改外部变量
    std::cout << "按钮被点击了 " << clickCount << " 次!" << std::endl;
});

为什么用 Lambda:事件处理代码直接嵌入,无需定义额外的函数。

5. Lambda 的深入理解

本质是什么?

Lambda 的底层是一个 匿名类的对象。编译器会做以下事情:

  1. 生成一个匿名类,类中重载了 operator()(即函数调用运算符)。

  2. 捕获的变量会变成这个类的成员变量。

  3. 当你调用 Lambda 时,实际是调用这个对象的 operator()

auto lambda = [x](int y) { return x + y; };

等价于

class __AnonymousClass {
public:
    __AnonymousClass(int x) : x_(x) {}
    int operator()(int y) const { return x_ + y; }
private:
    int x_;
};

__AnonymousClass lambda(x);
为什么好用?
  1. 简化代码:避免定义大量只用一次的小函数。

  2. 灵活捕获变量:直接使用上下文变量,无需传递参数。

  3. 支持函数式编程:可以像数据一样传递函数逻辑(如作为参数传给算法)。

6、注意事项

  1. 生命周期问题

    • 如果 Lambda 捕获了引用(如 [&x]),但外部的 x 被销毁了,Lambda 再执行会导致崩溃(悬挂引用)。

    • 解决方案:尽量用值捕获,或确保引用的变量生命周期足够长。

  2. 性能问题

    • 按值捕获大对象(如大数组)可能导致拷贝开销。可以用移动语义(C++14 支持移动捕获 [x = std::move(bigData)])。

  3. mutable 关键字

               1.默认 Lambda 是 const 的,不能修改按值捕获的变量。加 mutable 后可以修改:

int x = 1;
auto lambda = [x]() mutable { x++; }; // 允许修改内部的 x(外部的 x 不变)

总结

  • Lambda 是临时函数:随用随写,灵活高效。

  • 核心能力是捕获变量:按值或引用抓取外部变量。

  • 应用场景广泛:排序、事件回调、多线程、算法定制等。

  • 底层是匿名类对象:理解这一点能更好地控制它的行为。

最终建议:多用 Lambda 替代简单的一次性函数,但避免过度使用导致代码可读性下降。

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