C++中的lambda表达式

简介

  lambda表达式是C++11中引进的新特性之一,也是最常用的特性之一。lambda表达式来源于函数式编程的概念,也是现代编程语言的一个特点。
  lambda表达式具有以下特点:
  1. 不需要额外再写一个函数或者函数对象。
  2. 就地就可以匿名地定义一个目标函数或者函数对象。
  3. 在STL中用处很多。

基本语法和使用

  
  在C++中可以调用的对象有下面四种:

  • 函数
  • 函数指针
  • 函数对象(重载了函数调用运算符的类)
  • lambda表达式

      一个lambda表达式就是一个可调用的代码单元。可以将其理解为一个未命名的内联函数。与任何函数类似,lambda表达式有返回类型、参数列表和函数体,但是不同的是lambda表达式可能定义在函数内部(函数不能在函数内部定义)。
      
      lambda表达式的语法形式:
      

[捕获列表] (参数列表) -> 返回值类型 {函数体}

  其中,捕获列表是一个lambda所在函数中定义的局部变量的列表,其他和普通函数类似。

  我们可以忽略参数列表和返回值类型,但是必须永远包含捕获列表和函数体。因此一个完整的lambda表达式看起来像这样:
  

auto f = [] (int a) -> int { return a + 1; };
std::cout << f(1) << endl;      //输出: 2

  当省略lambda表达式的返回值类型时,当函数体中只有return语句时,编译器会自动推断返回值类型,但是函数体中除了return语句之外还有其他的语句后,编译器默认为返回void类型。

  lambda表达式可以用在STL中的谓词参数中。
  

stable_sort(words.begin(), words.end(), 
    [] (const string &a, const string &b)
    { return a.size() < b.size(); });

  当stable_sort 需要比较两个元素时,就会调用给定的lambda表达式。

lambda的捕获列表

  lambda表达式可以出现在函数中,使用其局部变量,但是他只能使用那些明确指明的变量。通过捕获列表来获得这些指明的变量,捕获列表指引lambda在其内部包含访问局部变量所需要的信息。

值捕获

  
  值捕获的前提是变量可以拷贝。与参数不同,被捕获的变量的值是在lambda创建时拷贝,而不是调用时拷贝,并且由于被捕获的变量是在lambda创建时的拷贝,因此随后的修改不会影响到lambda内对应的值。

void fcn1()
{
    size_t v1 = 42;   //局部变量
    //将v1拷贝到名为f的可调用对象
    auto f = [v1] { return v1; };
    v1 = 0;
    auto j = f();   //j为42,f保存了我们创建它时v1的拷贝
}

引用捕获

  引用捕获方式捕获的变量在lambda内使用的时候是引用所绑定的对象
  

void fcn2()
{
    size_t v1 = 42;   //局部变量
    //对象f2包含v1的引用
    auto f2 = [&v1] { return v1; };
    v1 = 0;
    auto j = f();   //j为0,f2保存了v1的引用,而非拷贝
}

  注意:如果我们采用引用方式捕获一个变量,就必须保证被引用的对象在lambda执行的时候是存在的。

隐式捕获

  让编译器根据lambda体中的代码推断使用哪些变量。
  

[=] 捕获外部作用域中的所有变量,并作为副本在函数体中使用
[&] 捕获外部作用域中的所有变量,并作为引用在函数体中使用
[=, &foo] 按值捕获外部作用域中的所有变量,并按引用捕获foo变量

可变lambda

  默认情况下,对于一个值被拷贝的变量,lambda不会改变其值,如果希望能改变被捕获的值,就必须在参数列表首加上关键字mutable
  

void fcn3()
{
    size_t v1 = 42;   //局部变量
    //f可以改变它所捕获的变量的值
    auto f = [v1] { return ++v1; };
    v1 = 0;
    auto j = f();   //j为43
}

  一个引用捕获的变量是否可以修改,依赖于此引用指向的是一个const类型还是一个非const类型:
  

void fcn3()
{
    size_t v1 = 42;   //局部变量
    // v1是一个非const变量的引用
    // 可以通过f2的引用来改变它
    auto f2 = [&v1] { return ++v1; };
    v1 = 0;
    auto j = f2();   //j为1
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值