一、Lambda 表达式简介

Lambda 表达式是 C++11 标准引入的特性,用于创建匿名函数对象(闭包)。它允许你在代码中直接定义一个函数,而无需显式命名。基本语法结构如下:

[capture](parameters) mutable -> return_type {
    // 函数体
}

各部分含义:

  1. [capture] (捕获列表):定义 Lambda 表达式如何访问外部变量
  2. (parameters) (参数列表):与普通函数参数列表类似
  3. mutable (可选项):允许修改捕获的值变量(不影响外部变量)
  4. -> return_type (可选项):显式指定返回类型
  5. { } (函数体):包含要执行的代码

二、捕获列表详解

捕获方式决定了 Lambda 如何访问外部作用域的变量:

  1. 值捕获:创建变量副本
    int a = 10;
    auto lambda = [a] { return a * 2; };  // 捕获a的值
    

  2. 引用捕获:直接操作原变量
    int b = 20;
    auto lambda = [&b] { b += 5; };  // 通过引用修改b
    

  3. 隐式捕获:
    • [=]:捕获所有外部变量(值方式)
    • [&]:捕获所有外部变量(引用方式)
    • [=, &x]:值捕获所有变量,但x用引用捕获

三、典型应用场景

  1. STL 算法:
    std::vector<int> nums{3,1,4,2};
    std::sort(nums.begin(), nums.end(), 
              [](int a, int b) { return a > b; });  // 降序排序
    

  2. 异步编程:
    std::thread t([=] {
        std::cout << "Value captured: " << a << std::endl;
    });
    t.join();
    

  3. 延迟执行:
    auto defer = [](auto func) {
        return std::make_shared<std::function<void()>>(func);
    };
    

四、C++14/17 增强特性

  1. 泛型 Lambda(C++14):
    auto generic = [](auto x, auto y) { return x + y; };
    

  2. constexpr Lambda(C++17):
    constexpr auto square = [](int n) { return n * n; };
    static_assert(square(5) == 25);
    

五、注意事项

  1. 生命周期管理:引用捕获需确保被引对象生命周期长于 Lambda
  2. 返回值推导:当函数体含多条语句时建议显式声明返回类型
  3. mutable 修饰:若需修改值捕获的副本必须使用 mutable
    int counter = 0;
    auto inc = [counter]() mutable { return ++counter; };  // 修改副本
    

六、示例:自定义比较器

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

int main() {
    std::vector<std::string> words{"apple", "banana", "cherry"};
    
    // 按长度排序
    std::sort(words.begin(), words.end(), 
              [](const std::string& a, const std::string& b) {
                  return a.length() < b.length();
              });
    
    for (const auto& w : words) {
        std::cout << w << " ";
    }
    // 输出:apple cherry banana
}

Lambda 表达式极大提升了代码的灵活性和简洁性,是现代 C++ 开发的核心工具之一。

好的,我们来详细讲解 C++ 中的 Lambda 表达式。

一、Lambda 表达式简介

Lambda 表达式是 C++11 标准引入的特性,用于创建匿名函数对象(闭包)。它允许你在代码中直接定义一个函数,而无需显式命名。基本语法结构如下:

[capture](parameters) mutable -> return_type {
    // 函数体
}

各部分含义:

  1. [capture] (捕获列表):定义 Lambda 表达式如何访问外部变量
  2. (parameters) (参数列表):与普通函数参数列表类似
  3. mutable (可选项):允许修改捕获的值变量(不影响外部变量)
  4. -> return_type (可选项):显式指定返回类型
  5. { } (函数体):包含要执行的代码

二、捕获列表详解

捕获方式决定了 Lambda 如何访问外部作用域的变量:

  1. 值捕获:创建变量副本
    int a = 10;
    auto lambda = [a] { return a * 2; };  // 捕获a的值
    

  2. 引用捕获:直接操作原变量
    int b = 20;
    auto lambda = [&b] { b += 5; };  // 通过引用修改b
    

  3. 隐式捕获:
    • [=]:捕获所有外部变量(值方式)
    • [&]:捕获所有外部变量(引用方式)
    • [=, &x]:值捕获所有变量,但x用引用捕获

三、典型应用场景

  1. STL 算法:
    std::vector<int> nums{3,1,4,2};
    std::sort(nums.begin(), nums.end(), 
              [](int a, int b) { return a > b; });  // 降序排序
    

  2. 异步编程:
    std::thread t([=] {
        std::cout << "Value captured: " << a << std::endl;
    });
    t.join();
    

  3. 延迟执行:
    auto defer = [](auto func) {
        return std::make_shared<std::function<void()>>(func);
    };
    

四、C++14/17 增强特性

  1. 泛型 Lambda(C++14):
    auto generic = [](auto x, auto y) { return x + y; };
    

  2. constexpr Lambda(C++17):
    constexpr auto square = [](int n) { return n * n; };
    static_assert(square(5) == 25);
    

五、注意事项

  1. 生命周期管理:引用捕获需确保被引对象生命周期长于 Lambda
  2. 返回值推导:当函数体含多条语句时建议显式声明返回类型
  3. mutable 修饰:若需修改值捕获的副本必须使用 mutable
    int counter = 0;
    auto inc = [counter]() mutable { return ++counter; };  // 修改副本
    

六、示例:自定义比较器

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

int main() {
    std::vector<std::string> words{"apple", "banana", "cherry"};
    
    // 按长度排序
    std::sort(words.begin(), words.end(), 
              [](const std::string& a, const std::string& b) {
                  return a.length() < b.length();
              });
    
    for (const auto& w : words) {
        std::cout << w << " ";
    }
    // 输出:apple cherry banana
}

Lambda 表达式极大提升了代码的灵活性和简洁性,是现代 C++ 开发的核心工具之一。

更多推荐