C++ Lambda 函数详解
Lambda 函数是在 C++11 引入的一种匿名函数,主要用于简化代码、就地定义回调函数 或临时函数。
语法形式: [capture](parameter_list) -> return_type
{
function_body;
};
• [capture] 捕获列表
o []:不捕获任何变量
o [=]:以值捕获所有外部变量(拷贝)
o [&]:以引用捕获所有外部变量
o [x]:仅以值捕获变量 x
o [&x]:仅以引用捕获变量 x
o [=, &y]:默认值捕获,y 使用引用捕获
o [&, x]:默认引用捕获,x 使用值捕获
• (parameter_list) 参数类似普通函数参数。可以省略,如果没有参数。
• -> return_type 返回类型,可以省略,编译器会自动推断(除非返回值复杂)。
• function_body 函数体,里面写要执行的代码。
基础示例
1. 最简单的 lambda
#include <iostream>
using namespace std;
int main() {
auto hello = []() { cout << "Hello Lambda!" << endl; };
hello();
}
输出:
Hello Lambda!
2. 带参数和返回值
#include <iostream>
using namespace std;
int main() {
auto add = [](int a, int b) -> int {
return a + b;
};
cout << add(3, 5) << endl; // 8
}
返回类型 -> int 可以省略,因为编译器能推断。
3. 捕获变量(值捕获)
#include <iostream>
using namespace std;
int main() {
int x = 10;
auto f = [=]() {
cout << "x = " << x << endl;
};
f();
}
输出:
x = 10
= 表示以值方式捕获变量。
4. 捕获变量(引用捕获)
#include <iostream>
using namespace std;
int main() {
int x = 10;
auto f = [&]() {
x += 5;
cout << "x = " << x << endl;
};
f();
cout << "after f, x = " << x << endl;
}
输出:
x = 15
after f, x = 15
& 表示引用捕获,修改会影响外部变量。
5. 混合捕获
#include <iostream>
using namespace std;
int main() {
int a = 1, b = 2;
auto f = [=, &b]() {
// a 按值捕获,不会改变外部
// b 按引用捕获,可以修改外部
cout << "inside: a=" << a << " b=" << b << endl;
// a++;
b++;
};
f();
cout << "outside: a=" << a << " b=" << b << endl;
}
输出:
inside: a=1 b=2
outside: a=1 b=3
6. 与 STL 算法结合
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4, 5};
// 打印
for_each(v.begin(), v.end(), [](int x){
cout << x << " ";
});
cout << endl;
// 统计大于 3 的个数
int count = count_if(v.begin(), v.end(), [](int x){
return x > 3;
});
cout << "count > 3: " << count << endl;
}
输出:
1 2 3 4 5
count > 3: 2
7. 排序自定义比较器
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> v = {5, 2, 9, 1};
sort(v.begin(), v.end(), [](int a, int b){
return a > b; // 降序
});
for (int x : v) cout << x << " ";
}
输出:
9 5 2 1
8. 延迟计算(闭包)
#include <iostream>
using namespace std;
int main() {
int base = 10;
auto make_adder = [=](int x) {
return [=](int y) {
return x + y + base;
};
};
auto add5 = make_adder(5); // base=10, x=5
cout << add5(3) << endl; // 18
}
9. 作为回调函数
#include <iostream>
#include <functional>
using namespace std;
void process(int x, function<void(int)> callback) {
cout << "Processing " << x << endl;
callback(x);
}
int main() {
process(42, [](int n){
cout << "Callback with " << n << endl;
});
}
输出:
Processing 42
Callback with 42
10. 可变 lambda(mutable)
默认情况下,值捕获的变量在lambda里不能修改,如果要修改,需要 mutable。
#include <iostream>
using namespace std;
int main() {
int x = 10;
auto f = [=]() mutable {
x += 5;
cout << "inside x=" << x << endl;
};
f();
cout << "outside x=" << x << endl;
}
输出:
inside x=15
outside x=10
mutable 只影响 lambda内部副本,不会改变外部 x。
总结:
1. 捕获方式:
o [=] 值捕获
o [&] 引用捕获
o [x] 指定变量
o [=, &y] 混合捕获
2. 常用场景:
o STL算法(排序、过滤、计数)
o 回调函数
o 封装闭包(延迟计算)
o 临时小工具函数
理解 C++ Lambda 的捕获方式,本质上就是搞清楚:
Lambda 内部函数体如何访问外部作用域的变量。
Lambda 捕获的本质
• Lambda 本质上是 一个匿名函数对象(闭包)。
• 编译器在生成这个对象的时候,会决定:
o 哪些外部变量需要被带进来(捕获)。
o 是以值拷贝(复制一个副本),还是 以引用(直接指向原变量)。
所以 捕获就是决定闭包和外部环境的交互方式。
捕获方式详解
1. 不捕获:[]
• 外部变量一律不能用。
int a = 10;
auto f = []() {
// cout << a; //
错误,a 未捕获
};
2. 值捕获:[=] 或 [x]
• 把外部变量复制一份到 Lambda 里。
• Lambda 内部拿到的是 副本,外部变量不会被修改。
int a = 10;
auto f = [=]() {
cout << "inside: " << a << endl;
};
f();
a = 20;
f();
输出:
inside: 10
inside: 10
因为 Lambda 保存的是 a 的拷贝。
3. 引用捕获:[&] 或 [&x]
• 把外部变量的引用传进来。
• Lambda 内部和外部变量是同一个。
int a = 10;
auto f = [&]() {
a += 5;
cout << "inside: " << a << endl;
};
f();
cout << "outside: " << a << endl;
输出:
inside: 15
outside: 15
4. 混合捕获:[=, &x] / [&, x]
• 可以指定 默认方式,同时给某些变量例外处理。
int a = 10, b = 20;
auto f = [=, &b]() {
// a 按值捕获
// b 按引用捕获
cout << "a=" << a << ", b=" << b << endl;
b += 10;
};
f();
cout << "outside: a=" << a << ", b=" << b << endl;
输出:
a=10, b=20
outside: a=10, b=30
5. 捕获 this
• 如果在类里面用 Lambda,默认捕获 this 指针。
#include <iostream>
using namespace std;
struct Test {
int x = 42;
void run() {
auto f = [=]() { cout << "x=" << x << endl; };
f();
}
};
int main() {
Test t;
t.run();
}
输出:
x=42
注意:这里 x 并不是直接捕获的,而是通过捕获 this 指针访问到的。
6. mutable 的值捕获
默认情况下,值捕获的变量在 Lambda 里是 const 的,如果要修改,需要 mutable。
int a = 10;
auto f = [=]() mutable {
a += 5; // 修改的是副本
cout << "inside: " << a << endl;
};
f();
cout << "outside: " << a << endl;
输出:
inside: 15
outside: 10
一个形象的比喻
• 值捕获(拷贝):就像拍了一张照片,你带着照片去 Lambda 里看,外面再怎么变,
你手里的照片不会变。
• 引用捕获(共享):就像把外面的窗户直接打开,Lambda 里看出去和外面看到的
是同一片风景,外面变化你也能看到。
更多推荐


所有评论(0)