在C++11中,lambda表达式是一种可以在调用点就地定义的匿名函数对象。它常用于标准算法如sort、for_each,以及异步任务的回调中,让代码更紧凑、可读性更高。要掌握lambda,首先要弄清楚它的基础语法结构,以及捕获列表如何把外部变量引入函数体。

lambda表达式的基础语法
一个典型的lambda表达式形式如下:
[capture](parameters) -> return_type {
// 函数体
return value;
}
其中各部分的含义是:
- capture:捕获列表,决定哪些外部变量可以在lambda内使用,以及按值还是按引用捕获。
- parameters:参数列表,和普通函数的参数一样,可省略当不需要参数时。
- return_type:返回类型,通常可以省略,由编译器自动推导。
- 函数体:具体的执行逻辑。
例如,一个最简单的lambda,用来返回两数之和:
auto add = [](int a, int b) {
return a + b;
};
int result = add(3, 4); // result为7
捕获列表的几种写法
捕获列表写在方括号里,它控制了lambda body对外部作用域变量的访问方式。常见形式有:
| 写法 | 含义 |
|---|---|
| [] | 不捕获任何外部变量 |
| [x] | 按值捕获变量x,lambda内拿到的是副本 |
| [&x] | 按引用捕获变量x,lambda内修改会影响外部 |
| [=] | 按值捕获所有外部变量 |
| [&] | 按引用捕获所有外部变量 |
| [=, &y] | 其余按值捕获,变量y按引用捕获 |
按值捕获示例
int base = 10;
auto f = [base](int x) {
return x + base; // base是副本,外部修改不影响这里
};
base = 20;
int v = f(5); // v为15,因为捕获时base是10
按引用捕获示例
int count = 0;
auto inc = [&count]() {
count++; // 修改的是外部count
};
inc();
inc();
// 此时外部count的值为2
捕获列表的注意事项
按值捕获的变量在lambda内默认是只读的,如果想修改,需要加mutable说明符:
int n = 0;
auto g = [n]() mutable {
n++;
return n;
};
捕获列表只捕获lambda定义时所在作用域里的局部变量,全局变量和静态变量不需要捕获即可直接使用。
在实际算法中的使用
配合标准库算法,lambda可以让代码非常直观。例如按字符串长度排序:
#include <vector>
#include <string>
#include <algorithm>
std::vector<std::string> words = {"apple", "hi", "banana"};
std::sort(words.begin(), words.end(),
[](const std::string& a, const std::string& b) {
return a.size() < b.size();
});
这里第三个参数就是一个lambda,作为自定义比较规则,不需要单独写一个函数对象类。
小结
lambda表达式通过[]捕获列表、()参数和函数体构成,捕获列表区分按值与按引用,是理解其行为的核心。掌握这些基础后,就能在C++11及以后的代码中自然地运用lambda提升表达力。