C++中的Lambda表达式详解

Lambda 表达式 是 C++11 引入的一种匿名函数语法,允许你在代码中直接定义和使用函数,而无需显式声明一个命名函数。Lambda 表达式通常用于简化代码,尤其是在需要传递函数作为参数的场景中(如 STL 算法、多线程编程等)。


1. Lambda 表达式的基本语法

Lambda 表达式的基本语法如下:

[capture](parameters) -> return_type 
{
    // 函数体
}
  • [capture]:捕获列表,用于指定外部变量的访问方式。

  • (parameters):参数列表,与普通函数的参数列表类似。

  • -> return_type:返回类型(可选,编译器可以自动推导)。

  • { ... }:函数体,包含具体的代码逻辑。

2. Lambda 表达式的组成部分

(1)捕获列表 [capture]

捕获列表用于指定 Lambda 表达式如何访问外部变量。常见的捕获方式包括:

  • [ ]:不捕获任何外部变量。

  • [=]:以值捕获所有外部变量。

  • [&]:以引用捕获所有外部变量。

  • [var]:以值捕获特定变量 var

  • [&var]:以引用捕获特定变量 var

  • [=, &var]:以值捕获所有外部变量,但以引用捕获 var

  • [&, var]:以引用捕获所有外部变量,但以值捕获 var

(2)参数列表 (parameters)

参数列表与普通函数的参数列表类似。如果没有参数,可以省略 ()

(3)返回类型 -> return_type

返回类型可以显式指定,也可以由编译器自动推导。如果函数体只有一条 return 语句,返回类型可以省略。

(4)函数体 { ... }

函数体包含 Lambda 表达式的具体逻辑。

3. Lambda 表达式的示例

示例 1:简单的 Lambda 表达式
#include
using namespace std;

int main()
{
	auto greet = []()
		{
			cout << "Hello Lambda!" << endl;
		};
	greet();
	return 0;
}
代码说明:
  • []:不捕获任何外部变量。

  • ():没有参数。

  • { ... }:函数体,输出 "Hello, World!"。

示例 2:带参数的 Lambda 表达式
#include
using namespace std;

int main()
{
	auto add = [](int a, int b)->int
		{
			return a + b;
		};
	cout << 'Sum:' << add(3, 4) << endl;
	return 0;
}
代码说明:
  • []:不捕获任何外部变量。

  • (int a, int b):两个整数参数。

  • -> int:显式指定返回类型为 int

  • { return a + b; }:函数体,返回两个参数的和。

示例 3:捕获外部变量
#include
using namespace std;

int main()
{
	int x = 10;
	int y = 20;

	auto sum = [x, &y]()->int
		{
			y = 30;//修改y的值
			return x + y;
		};

	cout << "Sum: " << sum() << endl;//输出40
	cout << "y:" << y << endl;//输出30
	return 0;
}

如果我们在y=30下一行加一个x=15,那么会报错:表达式必须是可修改的左值。为什么?我们过一会讲。

示例 4:Lambda 表达式与 STL 算法

Lambda 表达式常用于 STL 算法中,例如 std::sortstd::for_each 等。

#include
#include
#include
using namespace std;

int main()
{
	vectornumbers = { 3,1,4,1,5,9,2,6 };

	//使用lambda表达式排序
	sort(numbers.begin(), numbers.end(), [](int a, int b)
		{
			return a < b;
		});

	//使用lambda表达式打印每个元素
	for_each(numbers.begin(), numbers.end(), [](int n)
		{
			cout << n << " ";
		});

	return 0;
}
代码说明:
  • [](int a, int b) { return a < b; }:用于排序的 Lambda 表达式。

  • [](int n) { cout << n << " "; }:用于打印每个元素的 Lambda 表达式。

4. Lambda 表达式的优点

  1. 简洁性:可以在需要的地方直接定义函数,无需额外声明。

  2. 灵活性:可以捕获外部变量,适应不同的上下文。

  3. 功能性:可以作为参数传递给高阶函数(如 STL 算法)。


5. Lambda 表达式的注意事项

  1. 捕获列表的作用域

    • 值捕获的变量是只读的,除非使用 mutable 关键字

      #include
      using namespace std;
      
      int main()
      {
      	int x = 10;
      
      	auto modifyx = [x]()mutable
      		{
      			x += 5;//修改以值捕获的x
      			cout <<"Inside lambda:x = "<Inside lambda:x = 15
      Outside lambda:x = 10

      回到示例三中的问题:

      #include
      using namespace std;
      
      int main()
      {
      	int x = 10;
      	int y = 20;
      
      	auto sum = [x, &y]()->int
      		{
      			x = 15;//报错:表达式必须是可修改的左值
      			y = 30;//修改y的值
      			return x + y;
      		};
      
      	cout << "Sum: " << sum() << endl;//输出40
      	cout << "y:" << y << endl;//输出30
      	return 0;
      }

      x 的值不允许被修改的原因是 Lambda 表达式默认以值捕获的变量是只读的,除非使用 mutable 关键字显式允许修改。

      为什么 x 不能被修改?

      以值捕获的变量是只读的,当 Lambda 表达式以值捕获变量时(如 [x]),Lambda 函数体内会创建一个该变量的副本。默认情况下,这个副本是只读的,不能修改。如果需要在 Lambda 函数体内修改以值捕获的变量,必须使用 mutable 关键字。mutable 允许修改 Lambda 函数体内的副本,但不会影响外部的原始变量。引用捕获的变量可以修改外部变量的值。
      #include
      using namespace std;
      
      int main()
      {
          int x = 10;
          int y = 20;
      
          auto sum = [x, &y]() mutable -> int // 添加 mutable
          {
              x = 15;  // 现在可以修改 x
              y = 30;  // 修改 y 的值
              return x + y;
          };
      
          cout << "Sum: " << sum() << endl; // 输出 45
          cout << "x: " << x << endl;      // 输出 10(外部的 x 未被修改)
          cout << "y: " << y << endl;      // 输出 30(外部的 y 被修改)
          return 0;
      }

  2. 性能

    • Lambda 表达式通常会被编译器内联优化,性能接近普通函数。

    • 但如果捕获了大量变量或使用了复杂的逻辑,可能会影响性能。

 

你可能感兴趣的:(c++,开发语言)