Lambda表达式是一种用于定义匿名函数对象的便捷语法,自C++11引入后极大简化了代码编写,尤其是在需要传递短小函数逻辑的场景(如STL算法、回调函数等)
基本语法
[捕获列表] (参数列表) -> 返回类型
{
函数体
}
//eg
aotu add = [](int a, int b) -> int
{
return a + b;
}
cout << add(3, 4) << endl;
捕获列表(Capture List)
定义了Lambda表达式可以访问的外部变量及其访问方式(值捕获或引用捕获)
- []:不捕获任何外部变量
- [x]:按值捕获变量x
- [&x]:按引用捕获变量x
- [=]:按值捕获所有外部作用域的变量
- [&]:按引用捕获所有外部作用域的变量
- [=, &x]:按值捕获所有外部变量,但是按引用捕获变量x
- [&, x]:按引用捕获所有外部变量,但是按值捕获变量x
- [this]:捕获Lambda表达式所在的成员函数所属对象的指针
参数列表(parameters)
与普通函数的参数列表相同
可以为空
返回类型(return_type)
在大多数情况下,返回类型可以被省略,编译器会根据函数体中的返回语句自动推断返回类型
函数体(function body)
包含了Lambda函数的实现;
除了可以使用参数之外,还可以使用捕获变量
#include <iostream>
using namespace std;
int main(int argc, const char *argv[])
{
//不捕获任何外部变量[]
auto printHello = []()
{
cout << "[]--->" << "hello world" << endl;
};
printHello();//"hello world"
//按值捕获[x]
int x = 10;
auto add = [x](int a)
{
return a + x;
};
cout << "[x]-->" << add(5) << endl;//15
//按引用捕获[&x]
x = 10;
auto setX = [&x]()
{
x = 20;
};
setX();
cout << "[&x]-->" << x << endl;//20
//按值捕获所有外部变量[=]
x = 10;
int y = 20;
auto sum = [=]()
{
return x + y;
};
cout << "[=]-->" << sum() << endl;//30
//按引用捕获所有外部变量[&]
x = 10;
y = 20;
auto setXY = [&]()
{
x = 100;
y = 200;
};
setXY();
cout << "[&]-->" << x << " " << y << endl;//100 200
//按值捕获所有外部变量,但按引用捕获特定的变量[=, &x]
x = 10;
y = 20;
auto setXAndSum = [=, &x]()
{
x *= 2;
return x + y;
};
cout << "[=, &x]-->" << setXAndSum() << " " << "x = " << x << endl;//40 20
//按引用捕获所有外部变量,但按值捕获特定的变量[&, x]
x = 10;
y = 20;
auto setYAndSum = [&, x]()
{
y *= 2;
return x + y;
};
cout << "[&, x]-->" << setYAndSum() << " " << "y = " << y << endl;//50 40
return 0;
}
注意事项
-
如果使用值捕获,lambda表达式的一个特性:捕获的变量默认为常量,或者说lambda是一个常量函数
需要在函数体中修改变量值,需要加上说明符mutable,还多了一对()
语法规定lambda表达式如果存在说明符,那么形参列表不能省略mutable说明符是为了突破const的限制而设置的
被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中
#include <iostream> using namespace std; int main(int argc, const char *argv[]) { //按值捕获[x] int x = 10; auto add = [x] (int a) mutable { x = 100; return a + x; }; cout << "[x]-->" << add(5) << endl;//105 return 0; } -
Lambda表达式默认是const的,即它们不能修改捕获的变量的值,除非你明确指定捕获的变量为非const
-
使用Lambda表达式时,应注意其生命周期,特别是当按引用捕获外部变量时,必须确保被引用的变量在Lambda被调用时仍然有效
避免捕获局部变量的引用后超出其作用域(悬垂引用)
按值捕获的变量在Lambda创建时拷贝,后续外部变量修改不影响Lambda内的副本
-
性能优化:Lambda通常被编译器内联,性能接近手写代码;
避免在频繁调用的路径中捕获大型对象(按值捕获可能带来拷贝开销)
-
与std::function关系
Lambda可隐式转换为
std::function,但可能引入类型擦除开销直接使用auto存储lambda可保留类型信息,效率更高
底层实现
- Lambda表达式是通过生成一个匿名类(或称为闭包类型)的实例来实现的
- 这个匿名类内部重载了函数调用操作符operator() ,使得这个类的实例可以像函数一样被调用
- 每当定义一个Lambda表达式时,编译器会根据Lambda表达式的定义自动生成这样一个匿名类,并实例化一个该匿名类的对象
这个过程完全在编译时完成,不会导致运行时开销
// Lambda表达式
auto lambda = [x](int a) { return x + a; };
// 编译器生成的等效类
class __AnonymousLambda {
private:
int x; // 按值捕获的变量
public:
__AnonymousLambda(int x) : x(x) {}
int operator()(int a) const {
return x + a;
}
};
//编译器将lambda变量实例化为这个匿名类的对象
__AnonymousLambda lambda(x);
常用用法
与STL算法结合
std::vector<int> nums = {1, 2, 3, 4};
// 使用Lambda过滤偶数
auto it = std::remove_if(nums.begin(), nums.end(),
[](int n) { return n % 2 != 0; });
nums.erase(it, nums.end());
作为回调函数
//函数
//callback = [](int result)
void processDate(std::function<void(int)> callback)
{
cout << "processDate" << endl;
callback(42);//调用lambda的函数体
}
//调用processDate函数,传入Lambda表达式
processDate([](int result)
{
cout << "Result" << result;
}
Lambda高级特性
可变lambda(mutable关键字)
默认Lambda的 operator() 是 const 的,使用 mutable 允许修改按值捕获的变量:
int counter = 0;
auto increment = [counter]() mutable {
counter++;
std::cout << counter;
};
increment(); // 输出 1
increment(); // 输出 2(修改的是副本)
捕获表达式(C++14)
std::unique_ptr<int> ptr = std::make_unique<int>(42);
auto lambda = [p = std::move(ptr)]() {
std::cout << *p; // p 是移动后的 unique_ptr
};
模板lambda(C++20)
auto print = []<typename T>(T value) {
std::cout << value;
};
print(10); // T 推导为 int
print(3.14); // T 推导为 double
1693

被折叠的 条评论
为什么被折叠?



