跳转至

Lambda表达式基础

引言

我们在写一个排序函数,需要自定义比较规则。传统方式是:写一个单独的比较函数,或者写一个仿函数类。这两种方式都有点烦人——函数分离在别处,仿函数类又要写一堆样板代码。

然后,C++11带来了Lambda表达式,就像给你的代码送来了一台"一次性函数生成器"。

一句话总结:Lambda是匿名函数,可以就地定义和使用,特别适合作为回调函数和算法参数。


Lambda的基本语法

Lambda表达式的语法看起来有点吓人,但拆解后其实很清晰:

[capture](parameters) -> return_type { body }

各部分说明:

  • capture:捕获列表(后面章节详细讲)
  • parameters:参数列表(和普通函数一样)
  • return_type:返回类型(可以省略,编译器自动推导)
  • body:函数体

最简单的Lambda:

[]() { }              // 最简单:什么都不做
[]() { return 42; }   // 简单返回
[](int x) { return x * 2; }  // 带参数

实际使用:

auto add = [](int a, int b) { return a + b; };
int result = add(3, 4);  // result = 7
查看完整可编译示例
// Lambda Expression Basic Syntax
// Demonstrates the fundamental structure and syntax of C++ lambda expressions

#include <iostream>
#include <functional>

int main() {
    std::cout << "=== Lambda Basic Syntax Demo ===" << std::endl;

    // Lambda syntax: [capture](parameters) -> return_type { body }

    // Simplest lambda: does nothing
    auto do_nothing = []() {};
    do_nothing();
    std::cout << "Empty lambda executed" << std::endl;

    // Lambda with simple return
    auto return_42 = []() { return 42; };
    std::cout << "return_42() = " << return_42() << std::endl;

    // Lambda with parameter
    auto add = [](int a, int b) { return a + b; };
    int result = add(3, 4);
    std::cout << "add(3, 4) = " << result << std::endl;

    // Lambda with explicit return type
    auto complex = [](int x) -> int {
        if (x > 0) {
            return x * 2;
        } else {
            return x;
        }
    };
    std::cout << "complex(5) = " << complex(5) << std::endl;
    std::cout << "complex(-3) = " << complex(-3) << std::endl;

    // Lambda stored in std::function (has runtime overhead)
    std::function<int(int, int)> func = add;
    std::cout << "func(10, 20) = " << func(10, 20) << std::endl;

    // Using template parameters for zero overhead
    auto call_func = [](auto f) {
        return f(100, 200);
    };
    std::cout << "call_func(add) = " << call_func(add) << std::endl;

    return 0;
}

类型推导:自动识别返回类型

只要你的函数体只有一条return语句,编译器就能自动推导返回类型:

// 返回int,自动推导
auto square = [](int x) { return x * 2; };

// 返回double,自动推导
auto divide = [](int a, int b) { return static_cast<double>(a) / b; };

如果有多条语句,或者逻辑复杂,可以用->显式指定:

auto complex = [](int x) -> int {
    if (x > 0) {
        return x * 2;
    } else {
        return x;
    }
};
查看完整可编译示例
// Lambda Return Type Deduction
// Demonstrates automatic return type deduction in lambda expressions

#include <iostream>
#include <cmath>

int main() {
    std::cout << "=== Lambda Type Deduction Demo ===" << std::endl;

    // Automatic deduction for single return statement
    auto square = [](int x) { return x * x; };
    std::cout << "square(5) = " << square(5) << " (type: int)" << std::endl;

    // Deduction to double
    auto divide = [](int a, int b) {
        return static_cast<double>(a) / b;
    };
    std::cout << "divide(7, 2) = " << divide(7, 2) << " (type: double)" << std::endl;

    // Explicit return type for complex logic
    auto compute = [](int x) -> double {
        if (x > 0) {
            return std::sqrt(x);
        } else {
            return 0.0;
        }
    };
    std::cout << "compute(16) = " << compute(16) << std::endl;
    std::cout << "compute(-4) = " << compute(-4) << std::endl;

    // Lambda returning different types based on condition
    auto conditional = [](bool flag) {
        if (flag) {
            return 42;      // int
        } else {
            return 3.14;    // double - common type is double
        }
    };
    std::cout << "conditional(true) = " << conditional(true) << std::endl;
    std::cout << "conditional(false) = " << conditional(false) << std::endl;

    // decltype(auto) for perfect forwarding (C++14)
    auto identity = [](auto&& x) -> decltype(auto) {
        return std::forward<decltype(x)>(x);
    };
    int value = 100;
    int& ref = identity(value);
    ref = 200;
    std::cout << "After identity modification, value = " << value << std::endl;

    return 0;
}

作为算法参数:Lambda最常用的场景

Lambda表达式最经典的用法是作为STL算法的参数。这在嵌入式开发中同样有用,比如处理数据数组:

#include <algorithm>
#include <vector>

void process_sensor_data() {
    std::vector<int> readings = {12, 45, 23, 67, 34, 89, 56};

    // 找出第一个超过阈值的读数
    auto it = std::find_if(readings.begin(), readings.end(),
                          [](int value) { return value > 50; });

    // 统计有多少个异常值(>80)
    int count = std::count_if(readings.begin(), readings.end(),
                             [](int value) { return value > 80; });

    // 对所有值进行处理
    std::transform(readings.begin(), readings.end(), readings.begin(),
                  [](int value) { return value * 2; });
}

这比传统写函数干净太多了——逻辑就在使用的地方,不用跳来跳去。

查看完整可编译示例
// Lambda with STL Algorithms
// Demonstrates lambda expressions as arguments to STL algorithms

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

int main() {
    std::cout << "=== Lambda with STL Algorithms Demo ===" << std::endl;

    std::vector<int> readings = {12, 45, 23, 67, 34, 89, 56};

    // find_if: find first element matching condition
    auto it = std::find_if(readings.begin(), readings.end(),
                          [](int value) { return value > 50; });
    if (it != readings.end()) {
        std::cout << "First value > 50: " << *it << std::endl;
    }

    // count_if: count elements matching condition
    int count = std::count_if(readings.begin(), readings.end(),
                             [](int value) { return value > 80; });
    std::cout << "Values > 80: " << count << std::endl;

    // transform: apply function to each element
    std::vector<int> result;
    std::transform(readings.begin(), readings.end(), std::back_inserter(result),
                  [](int value) { return value * 2; });
    std::cout << "Transformed (x2): ";
    for (int v : result) {
        std::cout << v << " ";
    }
    std::cout << std::endl;

    // sort with custom comparator
    std::vector<int> data = {5, 2, 8, 1, 9};
    std::sort(data.begin(), data.end(), [](int a, int b) {
        return a > b;  // descending order
    });
    std::cout << "Sorted descending: ";
    for (int v : data) {
        std::cout << v << " ";
    }
    std::cout << std::endl;

    // accumulate with lambda
    int sum = std::accumulate(readings.begin(), readings.end(), 0,
                             [](int acc, int x) { return acc + x; });
    std::cout << "Sum: " << sum << std::endl;

    // for_each: perform action on each element
    std::cout << "Processing readings: ";
    std::for_each(readings.begin(), readings.end(), [](int value) {
        std::cout << "[" << value << "] ";
    });
    std::cout << std::endl;

    return 0;
}

捕获外部变量:让Lambda"看见"外面

虽然下一章会详细讲捕获,但这里先简单介绍基础概念。

默认情况下,Lambda不能访问外部变量:

int threshold = 50;
// ❌ 编译错误:threshold不可访问
auto lambda = [](int value) { return value > threshold; };

需要通过捕获列表"引入"外部变量:

int threshold = 50;

// 值捕获:复制一份threshold
auto by_value = [threshold](int value) { return value > threshold; };

// 引用捕获:使用外部的threshold
auto by_ref = [&threshold](int value) { return value > threshold; };

// 捕获所有变量(值捕获)
auto capture_all = [=](int value) { return value > threshold; };

// 捕获所有变量(引用捕获)
auto capture_all_ref = [&](int value) { return value > threshold; };

嵌入式场景示例:

void configure_pwm(uint32_t base_addr, int frequency) {
    // Lambda捕获base_addr和frequency
    auto set_duty = [base_addr, frequency](int percent) {
        uint32_t period = 1000000 / frequency;  // 微秒
        uint32_t duty = period * percent / 100;
        *reinterpret_cast<volatile uint32_t*>(base_addr + 0x04) = duty;
    };

    set_duty(25);   // 25%占空比
    set_duty(50);   // 50%占空比
    set_duty(75);   // 75%占空比
}
查看完整可编译示例
// Lambda Capture Basics
// Demonstrates how lambda captures external variables

#include <iostream>
#include <functional>
#include <cstdint>

int main() {
    std::cout << "=== Lambda Capture Basics Demo ===" << std::endl;

    // Value capture: copies the variable
    int threshold = 50;
    auto by_value = [threshold](int value) {
        return value > threshold;  // Uses the copied value
    };
    std::cout << "by_value(60) = " << by_value(60) << std::endl;
    threshold = 100;  // Modifying original doesn't affect lambda
    std::cout << "After threshold=100, by_value(60) = " << by_value(60) << std::endl;

    // Reference capture: references the original variable
    int count = 0;
    auto by_ref = [&count](int delta) {
        count += delta;  // Modifies the original
    };
    by_ref(10);
    by_ref(20);
    std::cout << "After by_ref(10) and by_ref(20), count = " << count << std::endl;

    // Capture all by value
    int x = 1, y = 2, z = 3;
    auto capture_all = [=]() {
        return x + y + z;  // All copied
    };
    std::cout << "capture_all() = " << capture_all() << std::endl;

    // Capture all by reference
    auto capture_all_ref = [&]() {
        x *= 2;
        y *= 2;
        z *= 2;
    };
    capture_all_ref();
    std::cout << "After capture_all_ref(), x=" << x << ", y=" << y << ", z=" << z << std::endl;

    // Mixed capture
    int multiplier = 2;
    int accumulator = 0;
    auto mixed = [multiplier, &accumulator](int value) {
        accumulator += value * multiplier;
    };
    mixed(5);
    mixed(10);
    std::cout << "After mixed(5) and mixed(10), accumulator = " << accumulator << std::endl;

    // Embedded example: PWM configuration with capture
    std::cout << "\n=== Embedded Example: PWM Config ===" << std::endl;

    uint32_t base_addr = 0x40000000;
    int frequency = 1000;

    auto set_duty = [base_addr, frequency](int percent) {
        uint32_t period = 1000000 / frequency;  // microseconds
        uint32_t duty = period * percent / 100;
        std::cout << "PWM: base=0x" << std::hex << base_addr << std::dec
                  << ", freq=" << frequency << "Hz, duty=" << duty << "us (" << percent << "%)" << std::endl;
    };

    set_duty(25);  // 25% duty cycle
    set_duty(50);  // 50% duty cycle
    set_duty(75);  // 75% duty cycle

    // Default capture warning
    std::cout << "\n=== Warning: Default Capture ===" << std::endl;
    int config = 100;
    int temp = 50;

    // Bad: captures everything by reference when only config is needed
    auto bad_capture = [&]() { return config > 50; };

    // Good: only capture what you need
    auto good_capture = [&config]() { return config > 50; };

    std::cout << "Use explicit capture to avoid unintended dependencies" << std::endl;

    return 0;
}

Lambda的类型:它到底是什么?

Lambda表达式的类型是唯一的、未命名的类类型。你不能直接声明Lambda类型,但可以用auto或者std::function

auto lambda1 = []() { };
// lambda1的类型是编译器生成的某个唯一类型

// 用std::function存储(有运行时开销)
std::function<void()> lambda2 = []() { };

// 用模板参数传递
template<typename Func>
void call_func(Func f) {
    f();
}
call_func([]() { /* ... */ });

嵌入式提示std::function有动态分配开销,优先使用auto或模板。


实战示例:事件处理器

假设你在做一个简单的GPIO事件处理系统:

#include <cstdint>
#include <functional>

class GPIOManager {
public:
    using EventHandler = std::function<void(uint32_t timestamp)>;

    // 注册上升沿事件处理
    void on_rising_edge(int pin, EventHandler handler) {
        rising_handlers[pin] = handler;
    }

    // 模拟硬件中断触发
    void simulate_interrupt(int pin, uint32_t timestamp) {
        auto it = rising_handlers.find(pin);
        if (it != rising_handlers.end() && it->second) {
            it->second(timestamp);  // 调用注册的Lambda
        }
    }

private:
    std::array<EventHandler, 16> rising_handlers;  // 假设16个引脚
};

// 使用示例
void setup_gpio_system() {
    GPIOManager gpio;

    int debounce_counter = 0;
    uint32_t last_press_time = 0;

    // 注册按键处理Lambda
    gpio.on_rising_edge([&](uint32_t timestamp) {
        // 防抖逻辑
        if (timestamp - last_press_time > 50) {  // 50ms防抖
            debounce_counter++;
            last_press_time = timestamp;
            // 触发业务逻辑...
        }
    });

    // 注册LED控制Lambda
    gpio.on_rising_edge([](uint32_t timestamp) {
        // 翻转LED
        static bool led_state = false;
        led_state = !led_state;
        // GPIO_Write(LED_PIN, led_state);
    }, 5);  // 引脚5
}
查看完整可编译示例
// Event Handler with Lambda
// Demonstrates lambda expressions for event handling in embedded systems

#include <iostream>
#include <functional>
#include <array>
#include <cstdint>

// Simple GPIO Manager with event handling
class GPIOManager {
public:
    using EventHandler = std::function<void(uint32_t timestamp)>;

    GPIOManager() : handlers{} {}

    void on_rising_edge(int pin, EventHandler handler) {
        if (pin >= 0 && pin < 16) {
            handlers[pin] = std::move(handler);
            std::cout << "Registered handler for pin " << pin << std::endl;
        }
    }

    void simulate_interrupt(int pin, uint32_t timestamp) {
        if (pin >= 0 && pin < 16 && handlers[pin]) {
            std::cout << "[IRQ " << timestamp << "ms] Pin " << pin << " triggered" << std::endl;
            handlers[pin](timestamp);
        }
    }

private:
    std::array<EventHandler, 16> rising_handlers;
};

// LED Controller example
class LEDController {
public:
    LEDController(int p) : pin(p), state(false) {}

    std::function<void(uint32_t)> get_toggle_handler() {
        return [this](uint32_t timestamp) {
            state = !state;
            std::cout << "  -> LED on pin " << pin << " toggled to "
                      << (state ? "ON" : "OFF") << std::endl;
        };
    }

private:
    int pin;
    bool state;
};

// Button with debounce
class Button {
public:
    Button(int p) : pin(p), debounce_count(0), last_press_time(0) {}

    std::function<void(uint32_t)> get_debounced_handler() {
        return [this](uint32_t timestamp) {
            // 50ms debounce
            if (timestamp - last_press_time > 50) {
                debounce_count++;
                last_press_time = timestamp;
                std::cout << "  -> Button " << pin << " pressed (count: "
                          << debounce_count << ")" << std::endl;
                on_press();
            }
        };
    }

    void on_press() {
        std::cout << "  -> Executing button action..." << std::endl;
    }

    int get_count() const { return debounce_count; }

private:
    int pin;
    int debounce_count;
    uint32_t last_press_time;
};

int main() {
    std::cout << "=== Event Handler Demo ===" << std::endl;

    GPIOManager gpio;

    // Example 1: Simple toggle handler
    std::cout << "\n--- Example 1: LED Toggle ---" << std::endl;
    LEDController led(5);
    gpio.on_rising_edge(5, led.get_toggle_handler());
    gpio.simulate_interrupt(5, 100);
    gpio.simulate_interrupt(5, 200);
    gpio.simulate_interrupt(5, 300);

    // Example 2: Debounced button
    std::cout << "\n--- Example 2: Debounced Button ---" << std::endl;
    Button button(3);
    gpio.on_rising_edge(3, button.get_debounced_handler());

    // Simulate rapid button presses (some should be debounced)
    gpio.simulate_interrupt(3, 500);   // Will register
    gpio.simulate_interrupt(3, 510);   // Debounced (too soon)
    gpio.simulate_interrupt(3, 520);   // Debounced
    gpio.simulate_interrupt(3, 600);   // Will register
    gpio.simulate_interrupt(3, 610);   // Debounced

    std::cout << "Total button presses registered: " << button.get_count() << std::endl;

    // Example 3: Lambda with captured context
    std::cout << "\n--- Example 3: Context Capture ---" << std::endl;
    int event_counter = 0;
    gpio.on_rising_edge(7, [&event_counter](uint32_t timestamp) {
        event_counter++;
        std::cout << "  -> Event #" << event_counter << " at " << timestamp << "ms" << std::endl;
    });

    gpio.simulate_interrupt(7, 1000);
    gpio.simulate_interrupt(7, 2000);
    gpio.simulate_interrupt(7, 3000);

    return 0;
}

实战示例:配置生成器

Lambda表达式可以用来创建"迷你配置语言":

struct TimerConfig {
    uint32_t prescaler = 0;
    uint32_t period = 0;
    bool auto_reload = false;
};

TimerConfig make_timer_config(std::function<void(TimerConfig&)> builder) {
    TimerConfig config;
    builder(config);
    return config;
}

// 使用:创建一个1kHz定时器配置
auto timer1_cfg = make_timer_config([](TimerConfig& c) {
    c.prescaler = 7200 - 1;     // 72MHz / 7200 = 10kHz
    c.period = 10 - 1;          // 10kHz / 10 = 1kHz
    c.auto_reload = true;
});

// 使用:创建一个PWM定时器配置
auto pwm_cfg = make_timer_config([](TimerConfig& c) {
    c.prescaler = 1 - 1;        // 不分频
    c.period = 1000 - 1;        // PWM周期
    c.auto_reload = true;
});

这种写法让配置代码非常清晰,所有参数都在一个地方集中管理。

查看完整可编译示例
// Configuration Builder Pattern with Lambda
// Demonstrates using lambda expressions to create fluent configuration APIs

#include <iostream>
#include <functional>
#include <cstdint>

// Timer configuration structure
struct TimerConfig {
    uint32_t prescaler = 0;
    uint32_t period = 0;
    bool auto_reload = false;
    uint32_t clock_div = 1;

    void print() const {
        std::cout << "TimerConfig: prescaler=" << prescaler
                  << ", period=" << period
                  << ", auto_reload=" << (auto_reload ? "yes" : "no")
                  << ", clock_div=" << clock_div << std::endl;
    }
};

// Configuration builder function
TimerConfig make_timer_config(std::function<void(TimerConfig&)> builder) {
    TimerConfig config;
    builder(config);
    return config;
}

// UART configuration structure
struct UARTConfig {
    uint32_t baudrate = 115200;
    uint8_t data_bits = 8;
    uint8_t stop_bits = 1;
    bool parity_enable = false;
    bool parity_odd = false;

    void print() const {
        std::cout << "UARTConfig: baudrate=" << baudrate
                  << ", data_bits=" << static_cast<int>(data_bits)
                  << ", stop_bits=" << static_cast<int>(stop_bits)
                  << ", parity=" << (parity_enable ? (parity_odd ? "odd" : "even") : "none")
                  << std::endl;
    }
};

UARTConfig make_uart_config(std::function<void(UARTConfig&)> builder) {
    UARTConfig config;
    builder(config);
    return config;
}

// Chainable builder for more complex scenarios
class GPIOConfigBuilder {
public:
    GPIOConfigBuilder(int pin) : pin_(pin) {}

    GPIOConfigBuilder& as_output() {
        config_.direction = "output";
        return *this;
    }

    GPIOConfigBuilder& as_input() {
        config_.direction = "input";
        return *this;
    }

    GPIOConfigBuilder& pull_up() {
        config_.pull = "up";
        return *this;
    }

    GPIOConfigBuilder& pull_down() {
        config_.pull = "down";
        return *this;
    }

    GPIOConfigBuilder& speed_high() {
        config_.speed = "high";
        return *this;
    }

    struct GPIOConfig {
        std::string direction = "input";
        std::string pull = "none";
        std::string speed = "low";
        int pin;
    };

    GPIOConfig build() {
        config_.pin = pin_;
        return config_;
    }

private:
    int pin_;
    GPIOConfig config_;
};

void print_gpio_config(const GPIOConfigBuilder::GPIOConfig& config) {
    std::cout << "GPIO Pin " << config.pin << ": "
              << config.direction << ", "
              << "pull=" << config.pull << ", "
              << "speed=" << config.speed << std::endl;
}

int main() {
    std::cout << "=== Configuration Builder Demo ===" << std::endl;

    // Example 1: 1kHz timer configuration using lambda
    std::cout << "\n--- 1kHz Timer Configuration ---" << std::endl;
    auto timer1_cfg = make_timer_config([](TimerConfig& c) {
        c.prescaler = 7200 - 1;    // 72MHz / 7200 = 10kHz
        c.period = 10 - 1;          // 10kHz / 10 = 1kHz
        c.auto_reload = true;
    });
    timer1_cfg.print();

    // Example 2: PWM timer configuration
    std::cout << "\n--- PWM Timer Configuration ---" << std::endl;
    auto pwm_cfg = make_timer_config([](TimerConfig& c) {
        c.prescaler = 1 - 1;        // No prescaling
        c.period = 1000 - 1;        // PWM period
        c.auto_reload = true;
        c.clock_div = 2;
    });
    pwm_cfg.print();

    // Example 3: UART configuration with lambda
    std::cout << "\n--- UART Configuration ---" << std::endl;
    auto uart_cfg = make_uart_config([](UARTConfig& c) {
        c.baudrate = 9600;
        c.data_bits = 8;
        c.stop_bits = 1;
        c.parity_enable = false;
    });
    uart_cfg.print();

    // Example 4: UART with parity
    std::cout << "\n--- UART with Parity ---" << std::endl;
    auto uart_parity = make_uart_config([](UARTConfig& c) {
        c.baudrate = 115200;
        c.data_bits = 9;           // 8 data + 1 parity
        c.parity_enable = true;
        c.parity_odd = true;
    });
    uart_parity.print();

    // Example 5: Chainable GPIO builder
    std::cout << "\n--- GPIO Chainable Builder ---" << std::endl;
    auto gpio5 = GPIOConfigBuilder(5)
        .as_output()
        .speed_high()
        .build();
    print_gpio_config(gpio5);

    auto gpio12 = GPIOConfigBuilder(12)
        .as_input()
        .pull_up()
        .build();
    print_gpio_config(gpio12);

    // Example 6: Configuration from variables
    std::cout << "\n--- Configuration from Variables ---" << std::endl;
    int target_frequency = 5000;
    int system_clock = 72000000;

    auto computed_cfg = make_timer_config([target_frequency, system_clock](TimerConfig& c) {
        int prescaler = system_clock / (target_frequency * 1000);
        c.prescaler = prescaler - 1;
        c.period = 999;
        c.auto_reload = true;
        std::cout << "Computed prescaler: " << prescaler << " for " << target_frequency << " Hz" << std::endl;
    });
    computed_cfg.print();

    // Example 7: Conditional configuration
    std::cout << "\n--- Conditional Configuration ---" << std::endl;
    bool high_speed_mode = true;

    auto adaptive_cfg = make_timer_config([high_speed_mode](TimerConfig& c) {
        if (high_speed_mode) {
            c.prescaler = 1;
            c.period = 999;
            c.clock_div = 1;
        } else {
            c.prescaler = 100;
            c.period = 999;
            c.clock_div = 2;
        }
    });
    adaptive_cfg.print();

    return 0;
}

泛型Lambda(C++14)

C++14让Lambda支持auto参数,变成模板函数:

// 泛型Lambda:可以接受任何可加类型
auto add = [](auto a, auto b) { return a + b; };

int x = add(3, 4);           // int
double y = add(3.5, 2.5);    // double

这在嵌入式开发中处理寄存器操作时特别有用:

auto write_reg = [](auto addr, auto value) {
    *reinterpret_cast<volatile decltype(value)*>(addr) = value;
};

write_reg(0x40000000, uint32_t(0x12345678));
write_reg(0x50000000, uint16_t(0xABCD));
查看完整可编译示例
// Generic Lambda (C++14)
// Demonstrates lambda expressions with auto parameters (template-like behavior)

#include <iostream>
#include <cstdint>
#include <string>

int main() {
    std::cout << "=== Generic Lambda Demo (C++14) ===" << std::endl;

    // Generic lambda: can accept any addable types
    auto add = [](auto a, auto b) {
        return a + b;
    };

    int int_result = add(3, 4);
    std::cout << "add(3, 4) = " << int_result << " (int)" << std::endl;

    double double_result = add(3.5, 2.5);
    std::cout << "add(3.5, 2.5) = " << double_result << " (double)" << std::endl;

    std::string concat = add(std::string("Hello, "), std::string("World!"));
    std::cout << "add(\"Hello, \", \"World!\") = " << concat << " (string)" << std::endl;

    // Generic lambda for register operations
    std::cout << "\n=== Generic Register Write ===" << std::endl;

    auto write_reg = [](auto addr, auto value) {
        using AddrType = decltype(addr);
        using ValueType = decltype(value);
        std::cout << "Write 0x" << std::hex << static_cast<unsigned long>(value)
                  << " to address 0x" << static_cast<unsigned long>(addr)
                  << std::dec << std::endl;
    };

    write_reg(0x40000000u, uint32_t(0x12345678));
    write_reg(0x50000000u, uint16_t(0xABCD));

    // Generic lambda with multiple auto parameters
    auto print_pair = [](auto first, auto second) {
        std::cout << "(" << first << ", " << second << ")" << std::endl;
    };

    print_pair(42, "answer");
    print_pair(3.14, "pi");
    print_pair('A', 65);

    // Generic lambda with perfect forwarding
    auto forward_and_print = [](auto&& x) -> decltype(auto) {
        std::cout << "Value: " << x << std::endl;
        return std::forward<decltype(x)>(x);
    };

    int value = 100;
    int& ref = forward_and_print(value);
    std::cout << "Original value address: " << &value << std::endl;
    std::cout << "Returned reference address: " << &ref << std::endl;

    // Generic lambda with conditional compilation
    auto process = [](auto x) {
        if constexpr (std::is_integral_v<decltype(x)>) {
            std::cout << "Processing integer: " << x << std::endl;
        } else if constexpr (std::is_floating_point_v<decltype(x)>) {
            std::cout << "Processing float: " << x << std::endl;
        } else {
            std::cout << "Processing other type" << std::endl;
        }
    };

    process(42);
    process(3.14);
    process("hello");

    return 0;
}

注意事项与最佳实践

1. 复杂度控制

如果Lambda超过5行,考虑把它命名或者提取成函数:

// ❌ 太长了,难以阅读
std::vector<int> result = std::accumulate(/* ... */, [](int acc, int x) {
    // ... 20行复杂逻辑 ...
});

// ✅ 提取成命名函数
int transform_element(int acc, int x);
std::vector<int> result = std::accumulate(/* ... */, transform_element);

2. 注意捕获的生命周期

引用捕获的变量必须保证在Lambda执行时仍然有效:

// ❌ 危险:返回后局部变量销毁
auto get_lambda() {
    int local = 42;
    return [&local]() { return local; };  // 悬垂引用!
}

// ✅ 安全:值捕获
auto get_lambda_safe() {
    int local = 42;
    return [local]() { return local; };  // 复制了一份
}

3. 嵌入式环境中避免动态分配

避免用std::function存储Lambda,使用auto或模板:

// ❌ 可能动态分配
std::function<void(int)> f = [](int x) { /* ... */ };

// ✅ 零开销
auto f = [](int x) { /* ... */ };

小结

Lambda表达式是现代C++的重要特性:

  • 就地定义:代码在使用的地方,逻辑清晰
  • 匿名函数:不需要额外命名,减少命名污染
  • 捕获机制:灵活控制外部变量访问
  • 算法友好:与STL算法配合使用,威力强大

在下一章,我们将深入了解Lambda的捕获机制及其对性能的影响。