C++ 什么是C++;11?

C++ 什么是C++;11?,c++,lambda,c++11,c++-faq,C++,Lambda,C++11,C++ Faq,什么是C++11中的lambda表达式?我什么时候用?在引入之前,他们解决了哪类问题是不可能的 一些示例和用例将非常有用 问题 C++包含有用的通用函数,如std::for_each和std::transform,非常方便。不幸的是,它们的使用也非常麻烦,特别是如果您想要应用的是特定函数所特有的 #include <algorithm> #include <vector> namespace { struct f { void operator()(int)

什么是C++11中的lambda表达式?我什么时候用?在引入之前,他们解决了哪类问题是不可能的

一些示例和用例将非常有用

问题 C++包含有用的通用函数,如
std::for_each
std::transform
,非常方便。不幸的是,它们的使用也非常麻烦,特别是如果您想要应用的是特定函数所特有的

#include <algorithm>
#include <vector>

namespace {
  struct f {
    void operator()(int) {
      // do something
    }
  };
}

void func(std::vector<int>& v) {
  f f;
  std::for_each(v.begin(), v.end(), f);
}
但是,这是不允许的,
f
不能传递给C++03中的函数

新的解决方案 C++11引入了lambda,它允许您编写一个内联匿名函子来替换结构f。对于小的简单示例,它可以更清晰地阅读(它将所有内容保存在一个位置),并且可能更易于维护,例如以最简单的形式:

void func3(std::vector<int>& v) {
  std::for_each(v.begin(), v.end(), [](int) { /* do something here*/ });
}
“捕获”变量 到目前为止,除了在lambda中传递给lambda的内容之外,我们没有使用任何其他内容,但是我们也可以在lambda中使用其他变量。如果要访问其他变量,可以使用capture子句(表达式的
[]
),该子句在这些示例中尚未使用,例如:

void func5(std::vector<double>& v, const double& epsilon) {
    std::transform(v.begin(), v.end(), v.begin(),
        [epsilon](double d) -> double {
            if (d < epsilon) {
                return 0;
            } else {
                return d;
            }
        });
}
void func5(std::vector&v,const double&epsilon){
std::transform(v.begin(),v.end(),v.begin(),
[ε](双d)->双d{
if(d
您可以通过引用和值进行捕获,可以分别使用
&
=
进行指定:

  • [&epsilon]
    通过引用捕获
  • [&]
    通过引用捕获lambda中使用的所有变量
  • [=]
    按值捕获lambda中使用的所有变量
  • [&,epsilon]
    捕获类似[&]的变量,但按值捕获epsilon
  • [=,&epsilon]
    捕获类似[=]的变量,但epsilon通过引用
默认情况下,生成的
operator()
const
,这意味着当您默认访问它们时,捕获将是
const
。这会导致使用相同输入的每个调用都会产生相同的结果,但是您可以请求生成的
运算符()
不是
const

什么是lambda函数? <λ函数的C++概念起源于λ演算和函数规划。lambda是一个未命名的函数,对于不可能重用且不值得命名的短代码片段非常有用(在实际编程中,而不是理论上)

在C++中,λ函数定义为这样的

[]() { } // barebone lambda
或者在它所有的荣耀里

[]() mutable -> T { } // T is the return type, still lacking throw()
[]
是捕获列表,
()
是参数列表,
{}
是函数体

捕获列表 捕获列表定义了lambda外部的哪些内容在函数体内部可用以及如何使用。 它可以是:

  • a值:[x]
  • 参考文献[&x]
  • 当前在引用范围内的任何变量[&]
  • 与3相同,但按值[=]
  • 您可以在逗号分隔的列表中混合上述任何内容
    [x,&y]

    参数列表

    参数列表与其他C++函数相同。 职能机构 实际调用lambda时将执行的代码

    返回类型扣除 如果lambda只有一个return语句,则返回类型可以省略,并具有隐式类型
    decltype(return\u语句)

    易变的 如果lambda被标记为可变的(例如,
    []()可变的{}
    ),则允许它对值捕获的值进行突变

    用例 ISO标准定义的库从lambdas中获益匪浅,并提高了几个栏的可用性,因为现在用户不必在一些可访问的范围内用小的functor来混乱代码

    C++14 在C++14中,lambda已通过各种建议进行了扩展

    初始化Lambda捕获 捕获列表的一个元素现在可以用
    =
    初始化。这允许重命名变量并通过移动进行捕获。标准中的一个示例:

    int x = 4;
    auto y = [&r = x, x = x+1]()->int {
                r += 2;
                return x+2;
             }();  // Updates ::x to 6, and initializes y to 7.
    
    还有一个来自维基百科,展示了如何使用
    std::move
    进行捕获:

    auto ptr = std::make_unique<int>(10); // See below for std::make_unique
    auto lambda = [ptr = std::move(ptr)] {return *ptr;};
    
    改进的返回类型扣除
    C++14允许为每个函数推导返回类型,并且不将其限制为
    返回表达式形式的函数。这也扩展到Lambda。

    Lambda表达式通常用于封装算法,以便将它们传递给另一个函数。但是,可以在定义后立即执行lambda

    [&](){ ...your code... }(); // immediately executed lambda expression
    
    在功能上等同于

    { ...your code... } // simple code block
    
    这使得lambda表达式成为重构复杂函数的强大工具。首先在lambda函数中包装一个代码段,如上所示。显式参数化过程可以在每一步之后通过中间测试逐步执行。一旦代码块完全参数化(如删除
    &
    所示),就可以将代码移动到外部位置并使其成为正常功能

    #include <algorithm>
    #include <vector>
    
    namespace {
      struct f {
        void operator()(int) {
          // do something
        }
      };
    }
    
    void func(std::vector<int>& v) {
      f f;
      std::for_each(v.begin(), v.end(), f);
    }
    
    类似地,您可以使用lambda表达式根据算法的结果初始化变量

    int a = []( int b ){ int r=1; while (b>0) r*=b--; return r; }(5); // 5!
    
    作为划分程序逻辑的一种方法,您甚至会发现将lambda表达式作为参数传递给另一个lambda表达式非常有用

    [&]( std::function<void()> algorithm ) // wrapper section
       {
       ...your wrapper code...
       algorithm();
       ...your wrapper code...
       }
    ([&]() // algorithm section
       {
       ...your algorithm code...
       });
    

    如果后续的分析显示函数对象的初始化开销很大,您可以选择将其作为普通函数重写。

    lambda函数是您在线创建的匿名函数。正如一些人解释的那样,它可以捕获变量(例如),但存在一些限制。例如,如果有一个回调
    #include <algorithm>
    #include <vector>
    
    namespace {
      struct f {
        void operator()(int) {
          // do something
        }
      };
    }
    
    void func(std::vector<int>& v) {
      f f;
      std::for_each(v.begin(), v.end(), f);
    }
    
    { ...your code... } // simple code block
    
    int a = []( int b ){ int r=1; while (b>0) r*=b--; return r; }(5); // 5!
    
    [&]( std::function<void()> algorithm ) // wrapper section
       {
       ...your wrapper code...
       algorithm();
       ...your wrapper code...
       }
    ([&]() // algorithm section
       {
       ...your algorithm code...
       });
    
    auto algorithm = [&]( double x, double m, double b ) -> double
       {
       return m*x+b;
       };
    
    int a=algorithm(1,2,3), b=algorithm(4,5,6);
    
    void apply(void (*f)(int)) {
        f(10);
        f(20);
        f(30);
    }
    
    int col=0;
    void output() {
        apply([](int data) {
            cout << data << ((++col % 10) ? ' ' : '\n');
        });
    }
    
    void output(int n) {
        int col=0;
        apply([&col,n](int data) {
            cout << data << ((++col % 10) ? ' ' : '\n');
        });
    }
    
    #include <functional> 
    
    #include <functional>
    void apply(std::function<void(int)> f) {
        f(10);
        f(20);
        f(30);
    }
    void output(int width) {
        int col;
        apply([width,&col](int data) {
            cout << data << ((++col % width) ? ' ' : '\n');
        });
    }
    
    auto x = [=](int arg1){printf("%i", arg1); };
    void(*f)(int) = x;
    f(1);
    x(1);
    
    [captureVar1,captureVar2](int arg1){}
    
       [&captureVar1,&captureVar2](int arg1){}
    
      [=](int arg1){} // capture all not-static vars by value
    
      [&](int arg1){} // capture all not-static vars by reference
    
    [=,&Param2](int arg1){} 
    
    [&,Param2](int arg1){} 
    
    [=](int arg1)->trailing_return_type{return trailing_return_type();}
    
    auto toFloat = [](int value) { return float(value);};
    auto interpolate = [min = toFloat(0), max = toFloat(255)](int value)->float { return (value - min) / (max - min);};
    
    void process_z_vec(vector<int>& vec)
    {
      auto print_2d = [](const vector<int>& board, int bsize)
      {
        for(int i = 0; i<bsize; i++)
        {
          for(int j=0; j<bsize; j++)
          {
            cout << board[bsize*i+j] << " ";
          }
          cout << "\n";
        }
      };
      // Do sth with the vec.
      print_2d(vec,x_size);
      // Do sth else with the vec.
      print_2d(vec,y_size);
      //... 
    }
    
    void print_modulo(const vector<int>& v, ostream& os, int m) // output v[i] to os if v[i]%m==0
    {
        for_each(begin(v),end(v),
            [&os,m](int x) { 
               if (x%m==0) os << x << '\n';
             });
    }
    
    class Modulo_print {
             ostream& os; // members to hold the capture list int m;
         public:
             Modulo_print(ostream& s, int mm) :os(s), m(mm) {} 
             void operator()(int x) const
               { 
                 if (x%m==0) os << x << '\n'; 
               }
    };
    
    void print_modulo(const vector<int>& v, ostream& os, int m) 
         // output v[i] to os if v[i]%m==0
    {
        class Modulo_print {
            ostream& os; // members to hold the capture list
            int m; 
            public:
               Modulo_print (ostream& s, int mm) :os(s), m(mm) {}
               void operator()(int x) const
               { 
                   if (x%m==0) os << x << '\n';
               }
         };
         for_each(begin(v),end(v),Modulo_print{os,m}); 
    }
    
    void print_modulo(const vector<int>& v, ostream& os, int m)
        // output v[i] to os if v[i]%m==0
    {
          auto Modulo_print = [&os,m] (int x) { if (x%m==0) os << x << '\n'; };
          for_each(begin(v),end(v),Modulo_print);
     }
    
    void TestFunctions::simpleLambda() {
        bool sensitive = true;
        std::vector<int> v = std::vector<int>({1,33,3,4,5,6,7});
    
        sort(v.begin(),v.end(),
             [sensitive](int x, int y) {
                 printf("\n%i\n",  x < y);
                 return sensitive ? x < y : abs(x) < abs(y);
             });
    
    
        printf("sorted");
        for_each(v.begin(), v.end(),
                 [](int x) {
                     printf("x - %i;", x);
                 }
                 );
    }
    
    int main()
    {
      // Lambda & auto
      int member=10;
      auto endGame = [=](int a, int b){ return a+b+member;};
    
      endGame(4,5);
    
      return 0;
    
    }
    
    int main()
    {
      int member = 10;
    
      class __lambda_6_18
      {
        int member;
        public: 
        inline /*constexpr */ int operator()(int a, int b) const
        {
          return a + b + member;
        }
    
        public: __lambda_6_18(int _member)
        : member{_member}
        {}
    
      };
    
      __lambda_6_18 endGame = __lambda_6_18{member};
      endGame.operator()(4, 5);
    
      return 0;
    }