学科分类
目录
C++基础

lambda表达式

C++11中引入了lambda表达式,用于定义匿名函数,使得代码执行更加灵活,方便了程序编写。一个lambda表达式表示一个可调用的代码单元,可将其理解为未命名的内联函数。与普通函数类似,lambda表达式也有参数表、返回值类型和函数体,但不同的是,lambda表达式可以定义在函数内部。lambda表达式的语法形式如下所示:

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

其中的“捕获列表”是由lambda表达式所在函数的局部变量构成的列表,通过捕获列表,lambda表达式可以使用所在函数的变量,捕获列表也可以为空。“参数列表”、“返回值类型”和“函数体”与普通函数中对应内容的含义相同。

下述代码在func()函数中定义了一个简单的lambda表达式,代码如下所示:

void func()
{
  int n = 5;          //func()函数的局部变量n
  //定义lambda表达式,捕获列表说明表达式中将使用函数中的变量n
  //表达式的参数为int x,表达式的返回值类型为bool,表达式实现了x和n的比较
  auto f = [n](int x)->bool { return x > n; };
  //通过f调用lambda表达式,传入实参值6,将完成6 > 5的比较,结果为true(1)
  cout << f(6) << endl;
}

上述代码中,在func()函数中定义了lambda表达式:[n](int x)->bool { return x > n; }, 表达式完成了参数x和func()函数局部变量n的比较,结果为bool值。变量f接收了lambda表示式,对表达式的调用与普通函数的调用方法相同,都是使用调用运算符“()”,如f(6)。

根据实际情况,也可以省略参数列表和返回值类型,但必须保留捕获列表和函数体,若程序中存在下面的lambda表达式,程序运行正确,代码如下所示:

auto f = []{return 10;};
cout << f() << endl;               //输出10

可以在容器中使用lambda表达式,简化程序编写。在func()函数中定义lambda表达式,操作vector容器,代码如下所示:

void func()
{
  vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  int value = 3;
   //通过count_if()计算容器中满足条件的元素个数,条件由lambda表达式给出。
   //本表达式中捕获列表为[=],表示可以使用本函数中所有局部变量的值
   int cnt = count_if(vec.cbegin(), vec.cend(), [=](int n){return n > value; });
  cout << "vector items : " << endl;
  //调用for_each()依次显示容器中的元素
  for_each(vec.begin(), vec.end(), [](int n){ cout << n << " "; });
  cout << "\nFind " << cnt << " values > " << value << endl;
}

上述代码中使用了两个lambda表达式,第一个表达式出现在count_if()函数第三个参数位置上,描述了计算条件,通过count_if()将计算出容器中大于3的元素为6个。第二个lambda表达式出现在for_each()函数第三个参数位置上,实现对每个元素的输出。

上面几段代码中使用了捕获列表的几种形式,现将捕获列表的可用形式总结如下:

● []:空捕获列表,表示lambda表达式不使用所在函数的任何变量。

● [变量列表]:变量列表是用逗号分隔的lambda表达式所在函数的多个局部变量,默认情况下,捕获列表中所有变量均对函数局部变量进行拷贝,若变量名称前使用了&,则采用引用方式捕获。

● [&]:隐式捕获列表,表示采用引用方式使用lambda表达式所在函数的局部变量。

● [=]:隐式捕获列表,采用值捕获方式使用所在函数的局部变量。

● [&, 变量列表]:变量列表中包含0个或多个lambda表达式所在函数的变量,对这些变量将采用值捕获方式进行操作,函数中其他的变量将采用引用捕获方式进行操作。

● [=, 变量列表]:变量列表中包含0个或多个lambda表达式所在函数的变量,对这些变量将采用引用捕获方式进行操作,函数中其他的变量将采用值捕获方式进行操作。

下面给出一段代码说明引用捕获的用法,代码如下:

void func2()
{
  vector<int> vec = { 1, 2, 3, 4, 5 };
  int index = 0;
  for_each(vec.begin(), vec.end(), 
  [&index](int n){ cout << "vec[" << (index++) << "]: " << n << endl; });
}

上述代码中使用了for_each()函数显示了容器中的每个元素及其下标,lambda表达式完成内容输出。在显示下标时使用了index变量,lambda表达式对index变量采用引用捕获方式,每显示一个元素index加1。

点击此处
隐藏目录