lambda表达式(c++)

1、lambda表达式是c++11 最重要也最常用的一个特性之一。lambda来源于函数式编程的概念,也是现代编程语言的一个特点。

lambda有以下优点:

    声明式编程风格:就地匿名定义目标函数或函数对象,不需要额外写一个命名函数或者函数对象。以更直接的方式去写程序,好的可读性和可维护性。

    简洁:不需要额外在写一个函数或函数对象,避免了代码膨胀和功能分散,让开发者更加击中精力在手边的问题,同时也获得了更高的生产率。

    在需要的时间和地点实现功能闭包,是程序更灵活。

2、语法如下:

[capture]    ( params )    opt -> ret { body; };

其中:

capture是捕获列表;params是参数表;opt是函数选项;ret是返回值类型;body是函数体。

auto f = [ ] (int a) -> int { return a + 1; };

std::cout << f(1) <<std::endl;        //输出2

很多时候lambda的表达式的返回值是很明显的,c++11中允许省略lambda的表达式:

auto f = [ ] (int a) { return a + 1; };

需要注意的是,初始化列表不能用于返回值的自动推导:

auto x = [ ] ( ) { return { 1, 2 }; };        //error:无法推导出返回值类型

另外,lambda 表达式在没有参数列表时,参数列表是可以省略的。因此,像下面的下发都是正确的(注意和上面区分):

auto  f1 = [ ]( ) { return 1; };

auto f2 = [ ] { return 1; };

lambda 表达式可以通过捕获列表捕获一定范围内的变量:

  1. [] 不捕获任何变量。
  2. [&]捕获外部作用域中所有变量,并作为引用在函数体中使用(按引用捕获)。
  3. [=]捕获外部作用域中所有变量,并作为副本在函数体中使用(按值捕获)。
  4. [=,&foo] 按值捕获外部作用域中所有变量,并按引用捕获foo 变量。
  5. [bar]按值捕获bar 变量,同时不捕获其他变量。
  6. [this]捕获当前类中的this 指针,让lambda 表达式拥有和当前类成员函数同样的访问权限。如果已经使用了 &或者=,就默认添加此选项
class A{
public:
	int i=0;

	void fun(int x,int y){
		auto x1=[]{ return i;};        //error,没有捕获外部变量
		auto x2=[=]{return i+x+y;};
		auto x3=[&]{return i+x+y;};
		auto x4=[this]{return i;};
		auto x5=[this]{return i+x+y;};        //error,没有捕获x, y
		auto x6=[this, x, y]{return i+x+y;};
		auto x7=[this]{return i++;};
	}
};
int main(){
	int a=0,b=1;
	auto f1=[]{return a;};        //error,没有捕获a变量
	auto f2=[&]{return a++;};
	auto f3=[=]{return a;};
	auto f4=[=]{return a++;};        //error,a是以复制方式捕获的,无法修改
	auto f5=[a]{return a++;};        //error,a只读,不能修改
	auto f6=[a]{return a;};
}

在上面的代码中,auto f4=[=]{return a++;};这是以复制方式捕获,无法修改,相当于const,如果我想修改它呢?

显然是有办法的,显示指明lambda 表达式为mutable:

int a=0;

auto f = [=] ( ) mutable { return a++; };            //这是编译器允许的,可以在本地编译器试一试。

需要注意一点的是,被mutable 修饰的lambda 表达式就算没有参数也要写明参数列表。

3、lambda表达式类型

最后,介绍一下lambda 表达式的类型。

lambda 在c++11中被称为 “闭包类型”。它是一个特殊的,匿名的非 nunion 的类类型。

因此,我可以们认为它是一个带有 operator() 的类,即仿函数。因此,我们可以调用std::function 和 std::bind 来存储和操作 lambda 表达式:

std::function<int(int)> f1=[ ](int a){ return a;};

std::function<int(void)> f2=std::bind( [ ] (int a) { return a; }, 123 );

猜你喜欢

转载自blog.csdn.net/godop/article/details/80150965