C++ 中的 Lambda 表达式
Lambda 表达式
C++11 中的 Lambda 表达式允许用户定义一个匿名函数(没有任何名称的函数),内联,它可以捕获周围作用域中的变量。这使得它们成为各种用例的强大功能,例如回调、排序、函数式编程等。
语法
以下是 C++ 中 lambda 表达式的语法:
[capture](parameters) -> return_type { function_body }
其中:
- capture 指定捕获外部作用域中的哪些变量。它可以通过值、引用或两种方式捕获变量。
- parameters 是 lambda 的输入参数。
- return_type 定义 lambda 函数的返回类型。如果需要显式定义返回类型,则应跟在 -> 符号之后。
- body 是 lambda 的主体部分,函数逻辑就写在这里。
Lambda 表达式示例
以下示例中,lambda 表达式用于将两个数字相加并返回结果:
#include <iostream> int main() { // 定义一个 lambda 表达式来将两个数字相加 auto add = [](int a, int b) { return a + b; }; // 调用 lambda 表达式 int result = add(5, 3); std::cout << "The sum of 5 and 3 is: " << result << std::endl; return 0; }
输出
The sum of 5 and 3 is: 8
在 Lambda 表达式中捕获变量
在 lambda 表达式中捕获变量允许 Lambda 访问其周围作用域的变量。通过捕获子句,Lambda 可以从其周围作用域捕获变量,并允许其在 Lambda 函数体内使用这些变量。
变量捕获的类型:
1. 按值捕获 ([x])
它通过 值 捕获 变量,这意味着 Lambda 会获得变量的副本,并且无法在 Lambda 函数体外修改原始变量。
[x](parameters) -> return_type { body }
2. Capture by reference ([&x])
It captures the variables by reference, which means here the lambda can access and modify the original variables.
[&x](parameters) -> return_type { body }
3. Capture Specific Variables ([x, &y])
This allows you to mix capture types in the same lambda. Here, the user can specify which variables to capture by value or reference.
[x, &y](parameters) -> return_type { body }
4. Captures all variables by value ([=])
It captures all variables in the surrounding scope by value.
[=](parameters) -> return_type { body }
5. Captures all variables by reference ([&])
It captures all variables in the surrounding scope by reference.
[&](parameters) -> return_type { body }
Capture this by reference ([this])
It captures this
pointer (a reference to the current object) in a lambda expression. It is useful when the user needs to access member variables or functions from within a lambda in a class method.
6. Capture by Mixed Modes
- [=, &x] ,It captures all variables by value and x variable by reference.
- [&, x] ,It captures all variables by reference and x by value.
- [=, this] ,It captures this pointer by value and all other variables by value.
Return Types in Lambda Expressions
In C++, lambda expressions return the value just like regular functions, and its return type can be automatically deduced by the compiler or explicitly specified by the programmer.
1. Automatic Return Type Deduction
In this, the compiler deduces the return type based on the return expression inside the lambda.
a) Implicit Return Type
In this, the return type is based on the return expression, which means users don't need to explicitly specify the return type; it will automatically be inferred from the type of the expression.
[capture](parameters) { return expression; }
b) Returning References
It returns references to variables or values; for this, make sure that the referenced variable stays in scope for the lifetime of the lambda.
[capture](parameters) -> type& { return reference; }
c) Returning Pointers
A lambda can also return a pointer to a variable or dynamically allocated memory.
[capture](parameters) -> type* { return pointer; }
d) Type Deduction with auto
Here, you can also use an auto
keyword for the return type, and the compiler will deduce the correct return value type based on an expression.
[capture](parameters) -> auto { return value; }
2. Explicit Return Type
In this, if the user wants to specify lambda's return type explicitly, then use -> return_type
syntax. This is useful when working with any complex types and when the return type isn't obvious.
[capture](parameters) -> return_type { return expression; }
Example
#include <iostream> using namespace std; int main() { int x = 5; int y = 10; auto my_lambda = [=, &x]() -> int { cout << "Inside lambda:" << endl; // can't modify 'y' as it's captured by value // Modifying 'x' as it's captured by reference x += 10; cout << "Captured 'x' by reference inside lambda: " << x << endl; // Captured 'y' by value, so it can't be modified here // simple operation with 'y' and a local value int sum = y + 5; cout << "Captured 'y' by value inside lambda: " << y << endl; cout << "Sum of 'y' and 5 inside lambda: " << sum << endl; return sum; }; // Call the lambda int result = my_lambda(); cout << "Result returned from lambda: " << result << endl; cout << "Value of 'x' outside lambda after modification: " << x << endl; cout << "Value of 'y' outside lambda (no modification): " << y << endl; return 0; }
当编译并执行上述代码时,它会产生以下结果 -
Inside lambda: Captured 'x' by reference inside lambda: 15 Captured 'y' by value inside lambda: 10 Sum of 'y' and 5 inside lambda: 15 Result returned from lambda: 15 Value of 'x' outside lambda after modification: 15 Value of 'y' outside lambda (no modification): 10
Recursive Lambdas
In C++, recursive lambda is the lambda function that calls itself over again and again during its execution until it reaches its base case. As lambda by default cannot call themselves directly, because they don't have a name. So for this, we can make lambda recursive by using a function pointer or std::function
.
Example
#include <iostream> #include <functional> // for std::function using namespace std; int main() { // Defining the recursive lambda using std::function std::function<int(int)> factorial = [&](int n) -> int { if (n <= 1) return 1; // Base case return n * factorial(n - 1); // Recursive call }; cout << "Factorial of 5: " << factorial(5) << endl; }
当编译并执行上述代码时,它会产生以下结果 -
Factorial of 5: 120