C++的lamda表达式,不用就忘记了_拔剑-浆糊的传说_新浪博客

 

lamda表达式,在python中也有,简单地说就是匿名函数。关于lamda表达式的例子和详细用法,我们可以参考这:http://en.wikipedia.org/wiki/Anonymous_function#C.2B.2B

C++11提供了对匿名函数的支持,称为Lambda函数(也叫Lambda表达式). Lambda表达式具体形式如下:
   [capture](parameters)->return-type{body}
capture:需要用到的外部变量,parameters:函数参数;body:函数体
  如果没有参数,空的圆括号()可以省略.返回值也可以省略,如果函数体只由一条return语句组成或返回类型为void的话.形如:
     [capture](parameters){body}
  下面举了几个Lambda函数的例子:  


[](int x, int y) { return x + y; } // 隐式返回类型
[](int& x) { ++x; }   // 没有return语句 -> lambda 函数的返回类型是'void'
[a](int& x) { x+=a; }   // 没有return语句 -> lambda 函数的返回类型是'void';注意,此处a是从lambda函数体外部传入其中的变量
[]() { ++global_x; }  // 没有参数,仅访问某个全局变量
[]{ ++global_x; }     // 与上一个相同,省略了(),可以像下面这样显示指定返回类型:  
[](int x, int y) -> int { int z = x + y; return z; }


  在这个例子中创建了一个临时变量z来存储中间值. 和普通函数一样,这个中间值不会保存到下次调用. 什么也不返回的Lambda函数可以省略返回类型, 而不需要使用 -> void 形式.
  Lambda函数可以引用在它之外声明的变量. 这些变量的集合叫做一个闭包. 闭包被定义在Lambda表达式声明中的方括号[]. 这个机制允许这些变量被按值或按引用捕获.下面这些例子就是:  

[]        //未定义变量.试图在Lambda内使用任何外部变量都是错误的.

[x, &y]   //x 按值捕获, y 按引用捕获.

[&]       //用到的任何外部变量都隐式按引用捕获

[=]       //用到的任何外部变量都隐式按值捕获

[&, x]    //x显式地按值捕获. 其它变量按引用捕获

[=, &z]   //z按引用捕获. 其它变量按值捕获

  接下来的两个例子演示了Lambda表达式的用法.  

std::vector < int > some_list;

int total = 0;

for (int i=0;i<5;++i) some_list.push_back(i);

std::for_each(begin(some_list), end(some_list), [&total](int x)

{

    total += x;

});

 

此例计算list中所有元素的总和. 变量total被存为lambda函数闭包的一部分. 因为它是栈变量(局部变量)total的引用,所以可以改变它的值.  

std::vector < int > some_list;

  int total = 0;

  int value = 5;

  std::for_each(begin(some_list), end(some_list), [&, value, this](int x)

  {

    total += x * value * this->some_func();

  });


  此例中total会存为引用, value则会存一份值拷贝. this的捕获比较特殊, 它只能按值捕获. this只有当包含它的最靠近它的函数不是静态成员函数时才能被捕获.protectpriviate成员来说, 这个lambda函数与创建它的成员函数有相同的访问控制. 如果this被捕获了,不管是显式还隐式的,那么它的类的作用域对Lambda函数就是可见的. 访问this的成员不必使用this->语法,可以直接访问.

不同编译器的具体实现可以有所不同,但期望的结果是:按引用捕获的任何变量,lambda函数实际存储的应该是这些变量在创建这个lambda函数的函数的栈指针,而不是lambda函数本身栈变量的引用. 不管怎样, 因为大数lambda函数都很小且在局部作用中, 与候选的内联函数很类似, 所以按引用捕获的那些变量不需要额外的存储空间.
  如果一个闭包含有局部变量的引用,在超出创建它的作用域之外的地方被使用的话,这种行为是未定义的!

lambda函数是一个依赖于实现的函数对象类型,这个类型的名字只有编译器知道. 如果用户想把lambda函数做为一个参数来传递, 那么形参的类型必须是模板类型或者必须能创建一个std::function类似的对象去捕获lambda函数.使用 auto关键字可以帮助存储lambda函数,  

--------- example from internet -------------------------

class CTest

{

public:

 CTest() : m_nData(20) { NULL; }

 void TestLambda()

 {

  vector vctTemp;

  vctTemp.push_back(1);

  vctTemp.push_back(2);

 

 

  // 无函数对象参数,输出:1 2

  {

   for_each(vctTemp.begin(), vctTemp.end(), [](int v){ cout << v << endl; });

  }

 

 

  // 以值方式传递作用域内所有可见的局部变量(包括this),输出:11 12

  {

   int a = 10;

   for_each(vctTemp.begin(), vctTemp.end(), [=](int v){ cout << v+a << endl; });

  }

 

 

  // 以引用方式传递作用域内所有可见的局部变量(包括this),输出:11 13 12

  {

   int a = 10;

   for_each(vctTemp.begin(), vctTemp.end(), [&](int v)mutable{ cout << v+a << endl; a++; });

   cout << a << endl;

  }

 

 

  // 以值方式传递局部变量a,输出:11 13 10

  {

   int a = 10;

   for_each(vctTemp.begin(), vctTemp.end(), [a](int v)mutable{ cout << v+a << endl; a++; });

   cout << a << endl;

  }

 

 

  // 以引用方式传递局部变量a,输出:11 13 12

  {

   int a = 10;

   for_each(vctTemp.begin(), vctTemp.end(), [&a](int v){ cout << v+a << endl; a++; });

   cout << a << endl;

  }

 

 

  // 传递this,输出:21 22

  {

   for_each(vctTemp.begin(), vctTemp.end(), [this](int v){ cout << v+m_nData << endl; });

  }

 

 

  // b按引用传递外,其他均按值传递,输出:11 12 17

  {

   int a = 10;

   int b = 15;

   for_each(vctTemp.begin(), vctTemp.end(), [=, &b](int v){ cout << v+a << endl; b++; });

   cout << b << endl;

  }

 

 

 

 

  // 操作符重载函数参数按引用传递,输出:2 3

  {

   for_each(vctTemp.begin(), vctTemp.end(), [](int &v){ v++; });

   for_each(vctTemp.begin(), vctTemp.end(), [](int v){ cout << v << endl; });

  }

 

 

  // 空的Lambda表达式

  {

   [](){}();

   []{}();

  }

 }

 

 

private:

 int m_nData;

};

---------- 来一段玄幻的代码,猜猜结果是啥? ----------------------------------   

 

cout<<[]()->int

     {

           int i = 0;

           for (int j = 0; j < 100; ++j)

           {

                [&]()

                {

                     i += j;

                }();

          }

          return i;

   }() << endl;

 

分析:

 

(1)里面有两个lamda函数,并且无名namda函数直接被执行了,没有用变脸存储

 

(2)最外面的lamda函数是:

 

[]()->int

{

           int i = 0;

         for (intj = 0; j < 100; ++j)

         {

                   ...

           }

      }

  由于该函数后面直接跟了(), 表示它被直接执行了,然后返回值被cout输出到屏幕上去了;

 

(3)然后for()循环中,也有个lamda函数,这个lamda函数由于后面也跟了个(),因此也被直接执行了  

 

[&]()

{ 

     i += j; 

}


4)最后输出的结果:4950


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值