C++11中的匿名函数指针(lambda函数,lambda表达式)  C++11提供了对匿名函数的⽀持,称为Lambda函数(也叫Lambda表达式). Lambda表达式具体形式如下:
    [capture](parameters)->return-type{body}
  如果没有参数,空的圆括号()可以省略.返回值也可以省略,如果函数体只由⼀条return语句组成或返回类型为void的话.形如:
    [capture](parameters){body}
  下⾯举了⼏个Lambda函数的例⼦:     
[](int x, int y) { return x + y; } // 隐式返回类型
[](int& x) { ++x; }  // 没有return语句 -> lambda 函数的返回类型是'void'
[]() { ++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只有当包含它的最靠近它的函数不是静态成员函数时才能被捕获.对protect和priviate成员来说, 这个lambda函数与创建它的成员函数有相同的访问控制. 如果this被捕获了,不管是显式还隐式的,那么它的类的作⽤域对Lambda函数就是可见的. 访问this的成员不必使⽤this->语法,可以直接访问.
  不同编译器的具体实现可以有所不同,但期望的结果是:按引⽤捕获的任何变量,lambda函数实际存储的应该是这些变量在创建这个lambda函数的函数的栈指针,⽽不是lambda函数本⾝栈变量的引⽤. 不管怎样, 因为⼤数lambda函数都很⼩且在局部作⽤中, 与候选的内联函数很类似, 所以按引⽤捕获的那些变量不需要额外的存储空间.
  如果⼀个闭包含有局部变量的引⽤,在超出创建它的作⽤域之外的地⽅被使⽤的话,这种⾏为是未定义的!
  lambda函数是⼀个依赖于实现的函数对象类型,这个类型的名字只有编译器知道. 如果⽤户想把lambda函数做为⼀个参数来传递, 那么形参的类型必须是模板类型或者必须能创建⼀个std::function类似的对象去捕获lambda函数.使⽤ auto关键字可以帮助存储lambda函数,
auto my_lambda_func = [&](int x) { /*...*/ };
auto my_onheap_lambda_func = new auto([=](int x) { /*...*/ });
  这⾥有⼀个例⼦, 把匿名函数存储在变量,数组或vector中,并把它们当做命名参数来传递
#include<functional>
#include<vector>
#include<iostream>
double eval(std::function<double(double)> f, double x = 2.0){return f(x);}
int main()
{
std::function<double(double)> f0    = [](double x){return 1;};
auto                          f1    = [](double x){return x;};
decltype(f0)                  fa[3] = {f0,f1,[](double x){return x*x;}};
std::vector<decltype(f0)>    fv    = {f0,f1};
fv.push_back                  ([](double x){return x*x;});
for(int i=0;i<fv.size();i++)  std::cout << fv[i](2.0) << "\n";
for(int i=0;i<3;i++)          std::cout << fa[i](2.0) << "\n";
for(auto &f : fv)            std::cout << f(2.0) << "\n";
for(auto &f : fa)            std::cout << f(2.0) << "\n";
std::cout << eval(f0) << "\n";
std::cout << eval(f1) << "\n";
return 0;
}
  ⼀个没有指定任何捕获的lambda函数,可以显式转换成⼀个具有相同声明形式函数指针.所以,像下⾯这样做是合法的:
auto a_lambda_func = [](int x) { /*...*/ };
void(*func_ptr)(int) = a_lambda_func;
func_ptr(4); //calls the lambda.

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。