Lambda 表达式是 C++11 引入的一种匿名函数,用于定义轻量级的可调用对象。它的基本语法如下:
[capture](parameters) -> return_type {
// 函数体
}
捕获列表用于指定 lambda 表达式如何访问外部作用域的变量。捕获方式包括:
this
捕获:捕获当前对象的 this
指针。*this
捕获(C++17):捕获当前对象的副本。示例:
int x = 10;
int y = 20;
// 值捕获
auto lambda1 = [x]() { return x; }; // x 被复制到 lambda 中
// 引用捕获
auto lambda2 = [&y]() { return y; }; // y 被引用捕获
// 混合捕获
auto lambda3 = [x, &y]() { return x + y; }; // x 被复制,y 被引用
// this 捕获
struct MyClass {
int value = 42;
auto get_lambda() {
return [this]() { return value; }; // 捕获 this 指针
}
};
// 初始化捕获(C++14)
auto lambda4 = [z = x + y]() { return z; }; // z 被初始化为 x + y
// *this 捕获(C++17)
auto lambda5 = [*this]() { return value; }; // 捕获当前对象的副本
参数列表与普通函数的参数列表类似,用于定义 lambda 表达式的输入参数。
示例:
auto add = [](int a, int b) { return a + b; };
std::cout << add(3, 4); // 输出 7
返回类型可以显式指定,也可以由编译器自动推导。如果函数体只有一条 return
语句,编译器可以自动推导返回类型。
示例:
// 自动推导返回类型
auto square = [](int x) { return x * x; };
// 显式指定返回类型
auto cube = [](int x) -> int { return x * x * x; };
函数体是 lambda 表达式的实现部分,包含具体的逻辑代码。
示例:
auto print = [](const std::string& msg) {
std::cout << msg << std::endl;
};
print("Hello, Lambda!");
mutable
:允许修改值捕获的变量。constexpr
(C++17):将 lambda 表达式声明为常量表达式。consteval
(C++20):将 lambda 表达式声明为立即求值的常量表达式。示例:
// mutable 示例
int a = 10;
auto lambda_mutable = [a]() mutable { a++; return a; };
std::cout << lambda_mutable(); // 输出 11,但外部的 a 仍然是 10
// constexpr 示例(C++17)
constexpr auto lambda_constexpr = [](int x) constexpr { return x * x; };
static_assert(lambda_constexpr(5) == 25); // 编译时计算
// consteval 示例(C++20)
consteval auto lambda_consteval = [](int x) consteval { return x * x; };
static_assert(lambda_consteval(5) == 25); // 编译时计算
C++20 允许 lambda 表达式使用模板形参。
示例:
auto generic_lambda = []<typename T>(T x) { return x * x; };
std::cout << generic_lambda(5) << std::endl; // 输出 25
std::cout << generic_lambda(3.14) << std::endl; // 输出 9.8596
IIFE 是一种在定义 lambda 表达式后立即调用的技术,通常用于限制变量的作用域。
示例:
int result = [](int a, int b) { return a + b; }(3, 4);
std::cout << result; // 输出 7
在捕获列表中直接初始化变量,可以在捕获时进行计算。
示例:
int x = 10;
int y = 20;
auto lambda = [z = x + y]() { return z; };
std::cout << lambda(); // 输出 30
auto
避免复制(C++14)在捕获列表中使用 auto
可以避免显式指定类型,同时避免不必要的复制。
示例:
std::string msg = "Hello";
auto lambda = [msg = std::move(msg)]() { return msg; };
std::cout << lambda(); // 输出 "Hello"
Lifting 是指将 lambda 表达式提升为函数对象,以便在更广泛的上下文中使用。
示例:
auto make_adder = [](int x) {
return [x](int y) { return x + y; };
};
auto add5 = make_adder(5);
std::cout << add5(10); // 输出 15
Lambda 表达式可以通过 std::function
实现递归调用。
示例:
std::function<int(int)> factorial = [&](int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
};
std::cout << factorial(5); // 输出 120
mutable
。std::function
或其他机制。int x = [] {
int a = 10;
int b = 20;
return a + b;
}();
std::cout << x; // 输出 30
int a = 10;
int b = 20;
auto lambda = [sum = a + b]() { return sum; };
std::cout << lambda(); // 输出 30
auto make_multiplier = [](int factor) {
return [factor](int x) { return x * factor; };
};
auto double_value = make_multiplier(2);
std::cout << double_value(5); // 输出 10
std::function<int(int)> fibonacci = [&](int n) {
return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
};
std::cout << fibonacci(10); // 输出 55