C++ Lambda

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

int main() {
    std::vector<int> v;
    v.push_back(1);
    v.push_back(5);
    int total = 0;
    std::for_each(v.begin(), v.end(), [&total](int x){ total += x; });

    std::cout << total;
}

Lambda函数中还有一个值得注意的地方,就是它的返回值类型。编译器一般会尽可能的(也是被要求的)推断lambda表达式的返回值类型,不过对于复杂的多行表达式而言,有可能会需要确切的声明返回值类型。返回值类型声明通过在lambda函数参数和函数主体之间添加-﹥运行符以及需要被声明的返回值类型来实现:

std::for_each(v.begin(), v.end(), [&](int x)-﹥void {total += x;});

[]()->{}
[函数对象参数] (操作符重载函数参数) mutable或exception声明 ->返回值类型 {函数体}
可以看到,Lambda主要分为五个部分:[函数对象参数]、(操作符重载函数参数)、mutable或exception声明、->返回值类型、{函数体}。下面分别进行介绍。
一、[函数对象参数],标识一个Lambda的开始,这部分必须存在,不能省略。函数对象参数是传递给编译器自动生成的函数对象类的构造函数的。函数对象参数只能使用那些到定义Lambda为止时Lambda所在作用范围内可见的局部变量(包括Lambda所在类的this)。函数对象参数有以下形式:
1、空。没有使用任何函数对象参数。
2、=。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。
3、&。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是引用传递方式(相当于编译器自动为我们按引用传递了所有局部变量)。
4、this。函数体内可以使用Lambda所在类中的成员变量。
5、a。将a按值进行传递。按值进行传递时,函数体内不能修改传递进来的a的拷贝,因为默认情况下函数是const的。要修改传递进来的a的拷贝,可以添加mutable修饰符。
6、&a。将a按引用进行传递。
7、a, &b。将a按值进行传递,b按引用进行传递。
8、=,&a, &b。除a和b按引用进行传递外,其他参数都按值进行传递。
9、&, a, b。除a和b按值进行传递外,其他参数都按引用进行传递。
二、(操作符重载函数参数),标识重载的()操作符的参数,没有参数时,这部分可以省略。参数可以通过按值(如:(a,b))和按引用(如:(&a,&b))两种方式进行传递。
三、mutable或exception声明,这部分可以省略。按值传递函数对象参数时,加上mutable修饰符后,可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)。exception声明用于指定函数抛出的异常,如抛出整数类型的异常,可以使用throw(int)。
四、->返回值类型,标识函数返回值的类型,当返回值为void,或者函数体中只有一处return的地方(此时编译器可以自动推断出返回值类型)时,这部分可以省略。
五、{函数体},标识函数的实现,这部分不能省略,但函数体可以为空

References:

C++11 http://zh.wikipedia.org/wiki/C%2B%2B11#Lambda.E5.87.BD.E5.BC.8F.E8.88.87.E8.A1.A8.E7.A4.BA.E5.BC.8F

<think>好的,我现在需要回答用户关于C++lambda表达式的使用教程。首先,我得回想一下自己对lambda的理解,并参考用户提供的三个引用内容,确保信息准确。用户给的引用里提到了lambda的基本结构、捕获列表、参数和返回类型,还有一些示例代码。我应该先整理这些知识点,分步骤讲解。可能需要从基本语法开始,然后讲捕获方式,再是参数和返回类型,最后举几个例子说明应用场景。要注意用户提到的系统级指令,比如数学公式用$...$,独立公式用$$...$$,但这个问题里可能数学公式不多,不过如果有的话要正确处理。另外,必须用中文回答,结构清晰,分步骤解决,还要生成相关问题。首先,lambda表达式的结构是[捕获列表](参数) mutable->返回类型 {函数体}。需要解释每个部分的作用,特别是捕获列表的不同方式:值捕获、引用捕获,以及隐式捕获=和&的区别。引用中的示例代码展示了这些用法,比如[=]和[a,c]的捕获方式,还有mutable关键字的使用,当需要修改捕获的变量时要用mutable。然后,参数列表和返回类型是可选的,可以自动推导。比如引用中的例子,有的没有参数,有的省略了返回类型。需要指出这些灵活性,并说明在哪些情况下可以省略。接下来,应用场景部分,可能需要举一些常见的例子,比如在STL算法中使用lambda作为谓词,或者用于回调函数、多线程等。引用中的例子主要是在main函数里直接调用,但实际中可能更多用于函数参数,比如std::sort的比较函数,或者std::for_each中的操作。 另外,要注意错误用法,比如捕获局部变量的引用后,变量生命周期结束导致的悬垂引用问题。需要提醒用户注意这一点,避免潜在bug。 最后,生成相关问题的时候,可以围绕lambda的捕获机制、mutable的作用、与函数指针的区别、性能考量等方面提问,确保覆盖用户可能感兴趣的扩展内容。 现在需要组织这些点,确保结构清晰,逐步引导用户理解。同时检查是否有遗漏的重要知识点,比如lambda的表达式的类型,它是匿名函数对象,可以赋值给auto变量。还有C++14之后的泛型lambda等新特性,但用户可能只需要基础教程,所以暂时不深入高级内容,除非引用中有提到。但根据提供的引用,似乎都是C++11的内容,所以保持在这个范围内。总结下来,回答的结构可能是: 1.基本语法结构2.捕获列表详解(值捕获、引用捕获、隐式捕获)3.mutable关键字的作用4.参数列表和返回类型的处理5.应用场景示例6.注意事项(如生命周期问题)然后每个部分配合引用中的代码示例,并标注引用标记。例如,在讲解捕获列表时,引用用户提供的第三个引用中的例子,说明如何捕获外部变量a和c。 最后,生成相关问题,比如如何选择捕获方式,lambda与函数对象的比较,mutable的必要性等。</think>### C++ Lambda表达式使用教程 Lambda表达式是C++11引入的匿名函数对象,常用于简化代码逻辑、实现回调函数或作为算法参数。以下是其核心用法和注意事项: --- #### 一、基本语法结构 Lambda表达式的基本格式为: $$[捕获列表](参数列表) \text{ mutable} \rightarrow 返回类型 \{ 函数体 \}$$ 其中**捕获列表**和**函数体**不可省略,其他部分可简化[^2]。 **示例**: ```cpp auto add = [](int x, int y) { return x + y; }; // 无捕获,参数为x和y cout << add(1, 2); // 输出3 ``` --- #### 二、捕获列表详解 捕获列表决定了Lambda如何访问外部变量: 1. **值捕获**:`[a, b]`,复制变量值到Lambda内部,默认不可修改(需`mutable`关键字)。 2. **引用捕获**:`[&a, &b]`,直接引用外部变量,可修改原值。 3. **隐式捕获**: - `[=]`:捕获所有外部变量为**值**。 - `[&]`:捕获所有外部变量为**引用**。 **示例**(值捕获与`mutable`): ```cpp int a = 10; auto func = [a]() mutable { a = 100; }; // 修改内部副本,不影响外部a[^1] ``` --- #### 三、参数与返回类型 1. **参数列表**:与普通函数参数类似,可传值或引用。 2. **返回类型**: - 若函数体仅有一个`return`语句,可自动推导返回类型。 - 复杂逻辑需显式指定`-> 返回类型`。 **示例**(自动推导返回类型): ```cpp auto print = [] { cout << "Hello"; }; // 无参数,无返回值 ``` --- #### 四、应用场景 1. **STL算法**:作为谓词函数传递给`std::sort`、`std::for_each`等。 ```cpp vector<int> nums = {3, 1, 4}; sort(nums.begin(), nums.end(), [](int a, int b) { return a > b; }); ``` 2. **异步编程**:在多线程中传递任务逻辑。 3. **简化局部代码**:替代一次性使用的函数对象。 --- #### 五、注意事项 1. **生命周期问题**:引用捕获需确保外部变量在Lambda调用时仍有效。 2. **性能影响**:值捕获可能产生拷贝开销,引用捕获需警惕悬垂引用。 3. **`mutable`限制**:仅允许修改Lambda内部捕获的副本,不影响外部变量。 **错误示例**: ```cpp int* p = new int(5); auto lambda = [&p] { delete p; }; // 可能导致多次释放 lambda(); ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值