C++ Lambda 表达式笔记(算法题向)

基础语法

[capture-list](parameter-list) -> return-type {
    // 函数体
}

两种递归 Lambda 写法对比

1. 使用 std::function 的递归 Lambda(C++11)

#include <functional>

std::function<int(int, int)> dfs = [&](int i, int j) -> int {
    // 基本情况
    if (i == 0 || j == 0) return 0;
    
    // 递归调用必须通过 dfs 名称
    return dfs(i-1, j) + dfs(i, j-1);
};

特点:

  • 需要包含 <functional> 头文件
  • 有运行时开销(类型擦除)
  • 适用于 C++11 及以后版本
  • 递归调用必须使用变量名 dfs

2. 使用显式对象参数的递归 Lambda(C++23)

auto dfs = [&](this auto&& self, int i, int j) -> int {
    // 基本情况
    if (i == 0 || j == 0) return 0;
    
    // 递归调用通过 self 参数
    return self(i-1, j) + self(i, j-1);
};

特点:

  • 不需要 std::function,零额外开销
  • 需要 C++23 支持
  • 更高效,直接使用 lambda 类型
  • 递归调用通过参数 self 进行
  • auto&& self 是通用引用,可以完美转发

算法题常见用法

记忆化搜索示例

// C++23 风格
auto dfs = [&](this auto&& self, int i, int j, auto& memo) -> int {
    if (memo[i][j] != -1) return memo[i][j];
    if (i == 0 || j == 0) return memo[i][j] = 0;
    
    return memo[i][j] = self(i-1, j, memo) + self(i, j-1, memo);
};

// C++11 风格
std::function<int(int, int, vector<vector<int>>&)> dfs = [&](int i, int j, auto& memo) -> int {
    if (memo[i][j] != -1) return memo[i][j];
    if (i == 0 || j == 0) return memo[i][j] = 0;
    
    return memo[i][j] = dfs(i-1, j, memo) + dfs(i, j-1, memo);
};

二叉树遍历示例

// C++23 风格
auto traverse = [&](this auto&& self, TreeNode* root) -> void {
    if (!root) return;
    self(root->left);  // 递归调用
    self(root->right);
};

捕获模式总结

捕获方式说明算法题常用场景
[&]引用捕获所有变量需要修改外部变量(如记忆化数组)
[=]值捕获所有变量需要只读访问外部变量(较少使用)
[var]值捕获特定变量需要特定变量的副本
[&var]引用捕获特定变量需要修改特定变量
[this]捕获当前类对象(类内定义 lambda 时)类方法中使用
[&, var]引用捕获所有变量,但值捕获 var大部分变量需要修改,个别需要副本
[=, &var]值捕获所有变量,但引用捕获 var大部分变量只读,个别需要修改

何时使用哪种写法

  1. 优先使用 C++23 风格(如果编译器支持):

    • 性能更好
    • 递归调用更直观
    • 不需要额外头文件
  2. 使用 std::function 风格

    • 需要支持 C++11/14/17
    • 需要将 lambda 存储在容器中或作为参数传递
    • 需要运行时多态(不同类型 lambda 统一存储)

性能提示

  1. 在递归深度较大时,C++23 风格通常更快
  2. 避免在循环中创建 std::function(会有重复分配开销)
  3. 对于简单算法,直接使用普通函数可能更高效

示例题目

斐波那契数列

// C++23 风格
auto fib = [](this auto&& self, int n) -> int {
    if (n <= 1) return n;
    return self(n-1) + self(n-2);
};

// C++11 风格
std::function<int(int)> fib = [&](int n) -> int {
    if (n <= 1) return n;
    return fib(n-1) + fib(n-2);
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值