C++lambda表达式

1、概念

构造一个闭包:一个匿名函数对象可以捕获作用域内的变量。其完整形式为:
[ captures ] (optional)(c++20) ( params ) specifiers exception attr -> ret requires(optional)(c++20) { body }

2、实例代码

  1. 一般实现模型,注意包含相应头文件。
// 可以使用如下类来替代lambda表达式
class Module_print {
private:
   std::ostream& os;
   int m;
public:
   // 注意引用必须使用成员列表初始化
   Module_print(std::ostream &s, int mm) : os(s), m(mm) { }
   // 注意默认情况下lambda无法修改捕获到的变量,故这里加const使其无法修改成员变量
   void operator()(int x) const
   {
   	if (x % m == 0) {
   		os << x << '\n';
   	}
   }
};
// 使用for_each需要包含头文件#include 
void print_module_v0(const std::vector& v, std::ostream& os, int m)
{
   for_each(begin(v), end(v), [&os, m](int x) {if (x % m == 0) os << x << '\n'; });
}

void print_module_v1(const std::vector& v, std::ostream& os, int m)
{
   for_each(begin(v), end(v), Module_print{os, m});
}
  1. 捕获列表以及返回值,详见代码注释
void lam_cap(void)
{
   char c = 'X';
   int  num = 6;
   double point = 9.8765;
   std::string str{"hello lambda"};
   
   // 空捕获列表无法捕获任何局部变量,但可以访问全局对象cout和endl.
   auto lam0 = [](void) { std::cout << "null" << std::endl; };	
   lam0();
   
   // 引用隐式捕获,所有局部变量都能通过引用访问
   auto lam1 = [&](void) { 
   std::cout << "lam1: The char c is " << c << "," 
   		      << "The num is " << num << "," 
   		      << "The point is " << point << ","
   		      << "The str is: " << str << std::endl; };
   lam1();

   // 值隐式捕获,所有局部变量都能通过值即副本访问
   auto lam2 = [=](void) {
   	std::cout << "lam2: The char c is " << c << ","
   		<< "The num is " << num << ","
   		<< "The point is " << point << ","
   		<< "The str is: " << str << std::endl; };
   lam2();

   // 通过引用捕获指定的局部变量num和c
   auto lam3 = [&num, &c](void) {
   std::cout << "lam3: The char c is " << c << ","
   			  << "The num is " << num   << std::endl; }; 
   lam3();

   // 通过值捕获指定的局部变量point和str
   auto lam4 = [point, str](void) {
   std::cout << "lam4: The point is " << point << ","
   		     << "The str is: " << str << std::endl; };
   lam4();

   // 除了局部变量c其他的局部变量均通过引用隐式捕获,这里c通过值捕获,注意列出的变量不能再以&开头了
   auto lam5 = [&, c](void) {
   std::cout << "lam5: The char c is " << c << ","
   		<< "The num is " << num << ","
   		<< "The point is " << point << ","
   		<< "The str is: " << str << std::endl; }; // 除了‘c’其他的都通过引用访问
   lam5();

   // 除了局部变量str靠引用捕获外其他的局部变量均通过值来捕获
   auto lam6 = [=, &str](void) {
   std::cout << "lam6: The char c is " << c << ","
   		<< "The num is " << num << ","
   		<< "The point is " << point << ","
   		<< "The str is: " << str << std::endl; }; // 除了str其他的都通过值传递
   lam6();

   // 通过“->”来显式指明其返回类型
   auto lam7 = [&]()->char {return c; };
   std::cout << "lam7 return is " << lam7() << std::endl;

   // 如果一个lambda什么也不捕获则可以将其赋给一个函数指针,否则只能使用auto
   int(*lam8)(int) = [](int a) {return a * a; }; 
   std::cout << "lam8 return is " << lam8(4) << std::endl;
}
  1. this指针以及mutable,当lambda被用于成员函数中时,我们可以将this放置在捕获列表中,访问类的成员变量
class Test {
private:
   char m_var0;
   int m_var1;
   double m_var2;
public:
   Test(const char arg1, const int arg2, const double arg3) : m_var0(arg1), m_var1(arg2), m_var2(arg3) { }
   void print_m(void)
   {
       	// 可以通过this指针访问成员变量
   	    // auto L1 = [this]() { std::cout << "m_var0 is " << m_var0 << ',' << "  m_var1 is " << m_var1 << ',' << " m_var2 is " << m_var2 << std::endl; }; 
   	    // 这样无法访问其成员变量
   	    // auto L1 = []() { std::cout << "m_var0 is " << m_var0 << ',' << "  m_var1 is " << m_var1 << ',' << " m_var2 is " << m_var2 << std::endl; }; 
   	    // 加mutable可以修改捕获到的成员变量
   		auto L1 = [this]() mutable { std::cout << "m_var0 is " << ++m_var0 << ',' << "  m_var1 is " << ++m_var1 << ',' << " m_var2 is " << ++m_var2 << std::endl; }; 
   		L1();
   }
};

你可能感兴趣的:(C++)