C++ 基础

C++ 主页 C++ 概述 C++ 环境设置 C++ 基本语法 C++ 注释 C++ Hello World C++ 省略命名空间 C++ 标记 C++ 常量/字面量 C++ 关键字 C++ 标识符 C++ 数据类型 C++ 数字数据类型 C++ 字符数据类型 C++ 布尔数据类型 C++ 变量类型 C++ 变量作用域 C++ 多变量 C++ 基本输入/输出 C++ 修饰符类型 C++ 存储类 C++ 数字 C++ 枚举 C++ 枚举类 C++ 引用 C++ 日期和时间

C++ 运算符

C++ 运算符 C++ 算术运算符 C++ 关系运算符 C++ 逻辑运算符 C++ 位运算符 C++ 赋值运算符 C++ sizeof 运算符 C++ 条件运算符 C++ 逗号运算符 C++ 成员运算符 C++ 强制类型转换运算符 C++ 指针运算符 C++ 运算符优先级 C++ 一元运算符

C++ 控制语句

C++ 决策语句 C++ if 语句 C++ if else 语句 C++ 嵌套 if 语句 C++ switch 语句 C++ 嵌套 switch语句 C++ 循环类型 C++ while 循环 C++ for 循环 C++ do while 循环 C++ Foreach 循环 C++ 嵌套循环 C++ break 语句 C++ continue 语句 C++ goto 语句

C++ 字符串

C++ 字符串 C++ 循环遍历字符串 C++ 字符串长度 C++ 字符串连接 C++ 字符串比较

C++ 函数

C++ 函数 C++ 多函数参数 C++ 递归函数 C++ 返回值 C++ 函数重载 C++ 函数重写 C++ 默认参数

C++ 数组

C++ 数组 C++ 多维数组 C++ 指向数组的指针 C++ 将数组传递给函数 C++ 从函数返回数组

C++ 结构 &联合

C++ 结构 C++ 联合

C++ 指针

C++ 指针 C++ 解引用 C++ 修改指针

C++ 类和对象

C++ 面向对象 C++ 类 &对象 C++ 类成员函数 C++ 类访问修饰符 C++ 静态类成员 C++ 静态数据成员 C++ 静态成员函数 C++ 内联函数 C++ this 指针 C++ 友元函数 C++ 指向类的指针

C++ 构造函数

C++ 构造函数 &析构函数 C++ 默认构造函数 C++ 参数化构造函数 C++ 复制构造函数 C++ 构造函数重载 C++ 带默认参数的构造函数 C++ 委托构造函数 C++ 构造函数初始化列表 C++ 使用构造函数动态初始化

C++ 继承

C++ 继承 C++ 多重继承 C++ 多级继承

C++ 面向对象

C++ 重载 C++ 多态性 C++ 抽象 C++ 封装 C++ 接口 C++ 虚函数 C++ 纯虚函数与抽象类

C++ 文件处理

C++ 文件和流 C++ 文件读取

C++ 进阶

C++ 异常处理 C++ 动态内存 C++ 命名空间 C++ 模板 C++ 预处理器 C++ 信号处理 C++ 多线程 C++ Web 编程 C++ 套接字编程 C++ 并发 C++ 高级概念 C++ Lambda 表达式 C++ unordered_multiset

C++ 实用资源

C++ 问答 C++ 快速指南 C++ 速查表 C++ STL 教程 C++ 标准库 C++ 实用资源 C++ 讨论


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