Lambda表达式基础¶
引言¶
我们在写一个排序函数,需要自定义比较规则。传统方式是:写一个单独的比较函数,或者写一个仿函数类。这两种方式都有点烦人——函数分离在别处,仿函数类又要写一堆样板代码。
然后,C++11带来了Lambda表达式,就像给你的代码送来了一台"一次性函数生成器"。
一句话总结:Lambda是匿名函数,可以就地定义和使用,特别适合作为回调函数和算法参数。
Lambda的基本语法¶
Lambda表达式的语法看起来有点吓人,但拆解后其实很清晰:
各部分说明:
capture:捕获列表(后面章节详细讲)parameters:参数列表(和普通函数一样)return_type:返回类型(可以省略,编译器自动推导)body:函数体
最简单的Lambda:
实际使用:
查看完整可编译示例
// 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; };
如果有多条语句,或者逻辑复杂,可以用->显式指定:
查看完整可编译示例
// 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的捕获机制及其对性能的影响。