lamda表达式

全文来自chatgpt

C++ 中的 lambda 表达式(也叫匿名函数)允许我们定义一个匿名的内联函数,它可以在需要函数指针或回调函数的地方使用,而不需要单独定义一个函数。这使得代码更加简洁,尤其是在处理函数对象、回调等场景时。

Lambda 表达式的基本语法

C++11 中引入了 lambda 表达式,其基本语法如下:

1
[捕获列表](参数列表) -> 返回类型 { 函数体 }

各部分的含义:

  1. 捕获列表(Capture List) [ ]
    • 捕获外部变量以便在 lambda 内部使用。
    • 可以指定哪些外部变量应该被传递给 lambda 表达式,或如何传递这些变量(按值、按引用等)。
    • 捕获方式:
      • [ ]:不捕获任何外部变量。
      • [x]:按值捕获外部变量 x
      • [&]:按引用捕获所有外部变量。
      • [=]:按值捕获所有外部变量。
      • [=, &x]:按值捕获所有外部变量,但按引用捕获 x
  2. 参数列表:类似于普通函数的参数列表,指定 lambda 表达式接受哪些参数。
  3. 返回类型(Optional)
    • 如果 lambda 表达式有返回值,可以通过 -> 指定返回类型。如果返回类型可以由编译器推导出,-> 可以省略。
  4. 函数体:包含 lambda 的执行代码,定义了函数的具体操作。

示例 1:一个简单的 lambda 表达式

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

int main() {
// 定义一个 lambda 表达式,捕获外部变量 i,并打印
int i = 10;
auto lambda = [i]() {
std::cout << "The value of i is: " << i << std::endl;
};

lambda(); // 调用 lambda 函数
return 0;
}
  • [i]:按值捕获外部变量 i
  • lambda 是 lambda 表达式的别名,可以像普通函数一样调用。

示例 2:捕获外部变量按引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

int main() {
int i = 10;

auto lambda = [&i]() {
i++; // 修改 i
std::cout << "The modified value of i is: " << i << std::endl;
};

lambda(); // 调用 lambda
std::cout << "The final value of i is: " << i << std::endl;
return 0;
}
  • [&i]:按引用捕获外部变量 i,允许在 lambda 内部修改它。

示例 3:指定参数列表和返回类型

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

int main() {
// 定义一个 lambda,接受两个参数并返回其和
auto add = [](int a, int b) -> int {
return a + b;
};

int result = add(5, 7);
std::cout << "Sum is: " << result << std::endl; // 输出 12
return 0;
}
  • [](int a, int b) -> int:定义了一个接受两个 int 参数并返回 int 类型结果的 lambda。

示例 4:没有返回值的 lambda

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>

int main() {
// 定义一个 lambda,打印两个数的和,但不返回
auto print_sum = [](int a, int b) {
std::cout << "The sum is: " << a + b << std::endl;
};

print_sum(3, 4); // 输出 The sum is: 7
return 0;
}
  • []:不捕获任何外部变量。
  • () -> void:没有返回值,void 可省略。

示例 5:lambda 作为参数传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <algorithm>
#include <vector>

int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};

// 使用 lambda 作为参数传递给 STL 算法
std::for_each(vec.begin(), vec.end(), [](int x) {
std::cout << x * x << std::endl; // 打印每个元素的平方
});

return 0;
}
  • 这里的 std::for_each 接受一个 lambda 表达式来对每个元素进行操作。

捕获外部变量的方式

  1. 按值捕获(Pass by Value)

    1
    2
    3
    int x = 10;
    auto lambda = [x]() { std::cout << x << std::endl; };
    // 捕获时会将 x 的值拷贝到 lambda 中,lambda 内修改 x 不会影响外部变量
  2. 按引用捕获(Pass by Reference)

    1
    2
    3
    int x = 10;
    auto lambda = [&x]() { std::cout << x << std::endl; };
    // 捕获时会引用外部变量 x,lambda 内修改 x 会影响外部变量
  3. 捕获所有外部变量(按值或按引用)

    • [=] 按值捕获所有外部变量。
    • [&] 按引用捕获所有外部变量。
  4. 混合捕获

    1
    2
    3
    4
    5
    int a = 10, b = 20;
    auto lambda = [a, &b]() {
    std::cout << "a: " << a << ", b: " << b << std::endl;
    };
    // 按值捕获 a,按引用捕获 b

小结

C++ 的 lambda 表达式提供了一种简洁的方式来定义匿名函数,可以灵活捕获外部变量并直接在函数体中使用。它广泛应用于 STL 算法、事件处理和回调函数等场景,是现代 C++ 编程中一个非常有用的特性。