lambda表达式

lambda表达式表示一个可调用的代码单元。我们可以认为它是一个未命名的内联函数。表达式形式如下:

[capture list] (parameter list) -> return type { function body }

capture list(捕获列表):lambda所在函数中的局部变量,供function body使用;

parameter list(参数列表):同普通函数;

return type(返回值):同普通函数,这个写法与普通函数不同,它是在函数尾部使用->;

function body(函数体):同普通函数。

我们可以忽略参数列表(等价于参数列表为空)和返回值(由类型推导来决定),但是捕获列表和函数体必须写。简单写法如下:

    auto func = [] {
        return 12;
    };
    std::cout << func() << std::endl;
稍微复杂一点的写法:

    auto func = []() -> int {
        return 12;
    };

打印vector所有成员:

    std::vector<std::string> vs;
    vs.push_back("what");
    vs.push_back("are");
    vs.push_back("you");
    vs.push_back("doing");

    std::for_each(vs.begin(), vs.end(), [](const std::string &str) {
        std::cout << str << " ";
    });
按字符串长短稳定的排序:

    std::stable_sort(vs.begin(), vs.end(), [](const std::string &left, const std::string &right) {
       return left.size() < right.size();
    });
加法:

    auto addFunc = [](int i, int j) {
        return i + j;
    };
    std::cout << addFunc(100, 200) << std::endl;
与普通函数不同,lambda不能有默认参数,也就是说形参和实参数目相等。


使用捕获列表:

1.值捕获,前提是变量可以拷贝,它不影响变量的原始值。

打印大于100的数

void func(const std::vector<int> &vi)
{
    int dst = 100;
    std::for_each(vi.begin(), vi.end(), [dst](int i) {
       if (i > dst) {
           std::cout << i << " ";
       }
    });
}
其中dst就是捕获的局部变量。

2.引用捕获与引用变量一样,在lambda执行的时候必须保证被引用的对象存在。如果lambda在函数结束后执行,捕获的引用指向的局部变量已经销毁了。
在lambda表达式中修改一个捕获的局部变量

void func()
{
    int dst = 100;
    auto f = [&dst] {
        dst = 200;
    };
    f();
    std::cout << dst << std::endl;
}
结果是200


3.使用this捕获成员变量

class Test
{
public:
    Test(int number) : number_(number) { }
    void print()
    {
        auto f = [this] {
            std::cout << number_ << std::endl;
        };
        f();
    }

private:
    int number_;
};


4.隐式捕获

[&]   采用引用的方式进行隐式捕获,lambda体中所捕获的局部变量都是引用捕获;

[=]  采用值拷贝的方式进行隐式捕获,lambda体中所捕获的局部变量都是值捕获;

[&, identifier_list]   identifier_list是一个逗号分隔的列表,包含0个或多个来自所在函数的变量。这些变量采用值捕获方式,而任何隐式捕获的变量都采用引用方式捕获。即,identifier_list中的名字前面不能使用&。

[=, identifier_list]    identifier_list中的变量都采用引用方式捕获,而任何隐式捕获的变量都是采用值方式捕获。identifier_list中的名字不能包含this,且这些名字之前必须使用&。

可变lambda

默认情况下,对于一个值捕获的变量lambda不会改变其值,编译也是通不过的。

但是有时候确实有这样的需求,那么必须在参数列表后面加上mutable,此时的参数列表不能省略,如下:

void func()
{
    int i = 0;
    auto f = [i] () mutable {
        ++i;
        std::cout << i << std::endl;
    };
    f();
    std::cout << i << std::endl;
}
输出1和0。虽然lambda改变了i的值,但也只是对lambda有效,在外部i的值还是为0,这样也与值捕获吻合。当然如果外部想使用改变后的值可以对它进行return,或者使用引用捕获。


<think>我们正在讨论Lambda表达式。根据用户需求,用户想了解Lambda表达式的概念和用法,以及在编程中的使用和示例。根据提供的引用,我们可以总结如下:引用[1]:Lambda表达式在函数式编程、并发编程和简化代码等方面有广泛应用(Java)。引用[2]:C++Lambda表达式可以定义匿名函数,具有参数、返回值、捕获等特性。引用[3]:Scala中Lambda表达式有简写方式,左侧参数列表,右侧表达式,可以有返回值。引用[4]:C#中Lambda表达式可以转换为表达式树,用于动态生成代码,也用于异步编程。因此,我们可以从以下几个方面介绍:1.概念:Lambda表达式是一种匿名函数,可以捕获上下文变量,通常用于简化代码和实现函数式编程。2.用法:在不同语言中的语法和特性。3.示例:展示几种常见语言中的Lambda表达式示例。注意:回答中引用的段落末尾要添加引用标识,如[^1]。但注意,我们实际引用的内容来自用户提供的引用,所以需要对应。由于用户要求使用中文,并且要求生成相关问题,我们在最后生成相关问题。另外,注意数学表达式的格式要求(但本问题可能较少涉及数学表达式,如果有则按规则处理)。结构:一、Lambda表达式的概念二、Lambda表达式的一般特点三、不同编程语言中的Lambda表达式用法和示例1.Java2.C++3.Scala4.C#四、总结五、生成相关问题注意:引用标识的添加要自然,在引用内容的末尾添加。</think>### Lambda表达式的概念、用法与示例 #### 一、概念解析 Lambda表达式是一种**匿名函数**的简洁表示方式,核心特点包括: 1. **无函数名**:无需显式定义函数名称 2. **即时定义**:可在需要函数对象的位置直接声明 3. **捕获上下文**:可访问外部作用域的变量(通过值捕获或引用捕获) 4. **函数式编程核心**:支持高阶函数操作(如map/filter/reduce) 其通用语法为: `(参数列表) -> { 函数体 }` 在类型推断明确的场景中,参数类型和花括号常可省略[^2][^3]。 #### 二、核心应用场景 1. **简化回调函数**(事件处理/异步编程) 2. **集合操作**(流式处理/数据转换) 3. **替代单方法接口**(如Java的Runnable/Comparator) 4. **延迟执行逻辑**(表达式树/惰性求值) 5. **并发编程**(线程任务封装)[^1][^4] #### 三、多语言示例 ##### 1. Java:集合过滤 ```java List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); // Lambda过滤长度>3的字符串 List<String> filtered = names.stream() .filter(s -> s.length() > 3) .collect(Collectors.toList()); // 输出: [Alice, Charlie] ``` `->` 符号连接参数表达式,实现`Predicate`接口的简写[^1]。 ##### 2. C++:自定义排序 ```cpp std::vector<int> nums = {5, 3, 7, 1}; // Lambda实现降序排序 std::sort(nums.begin(), nums.end(), [](int a, int b) { return a > b; }); // 结果: {7, 5, 3, 1} ``` `[]`为捕获列表,此处为空表示不捕获外部变量[^2]。 ##### 3. C#:表达式树 ```csharp // 将Lambda转换为表达式树 Expression<Func<int, int, int>> expr = (a, b) => a * b + 2; var compiled = expr.Compile(); Console.WriteLine(compiled(3, 4)); // 输出14 ``` 此特性被ORM框架广泛用于SQL查询转换[^4]。 ##### 4. Scala:高阶函数 ```scala val numbers = List(1, 2, 3, 4) // Lambda实现平方映射 val squares = numbers.map(x => x * x) // 结果: List(1, 4, 9, 16) ``` 箭头`=>`左侧为参数,右侧为表达式[^3]。 #### 四、关键优势 1. **代码简洁性**:减少模板代码(如Java匿名类) 2. **可读性提升**:逻辑更贴近调用点 3. **函数组合能力**:支持链式操作(如Java Stream API) 4. **运行时优化**:延迟执行提升性能(如C#表达式树)[^4] > Lambda表达式已成为现代编程语言的标配特性,在函数式编程范式、并发处理和API简化方面发挥着关键作用[^1][^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值