cpp_3_2_Lambda 表达式

  1. Overview
  2. cpp Lambda 表达式的语法
  3. capture List 捕获列表
  4. Reference

Overview

1.cpp Lambda 表达式的语法
2.capture List 捕获列表

cpp Lambda 表达式的语法

1.Lambda 表达式为cpp引入匿名函数, 和 python 的lambda函数做的事一样, 匿名函数的存在可以允许我们不给函数起名使得代码非常紧凑;
2.Lambda 表达式将函数名称被省略了, 返回值使用了一个很形象的单箭头 -> 的形式来写, 语法如下:

[capture list] (parameter list)  mutable(optional) exception attribute -> return_type {
// function body
}

实际开发中最常见以下2种

[capture list] (parameter list) {function body}
[capture list] {function body}

上面的语法除了[capture list] (捕获列表) 外, 其他部分都容易理解, 先写一个基础的例子感受下lambda对于代码的简化;

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

bool cmp(int& lhs, int& rhs) {
  return lhs < rhs;
}

int main() {
  vector<int> v1{3, 2, 5, 7, 4, 1};
  vector<int> v2(v1);

  sort(v1.begin(), v1.end(), cmp);
  cout << "ori func: ";
  for (auto& e : v1) {
    cout << e << ' ';
  }
  cout << endl;

  sort(v2.begin(), v2.end(), [](int& lhs, int& rhs) -> bool {
    return lhs < rhs;
  });
  cout << "lambda: ";
  for (auto& e : v2) {
    cout << e << ' ';
  }
  cout << endl;
  return 0;
}

capture List 捕获列表

1.所谓捕获列表, 可以理解为参数的一种类型; Lambda 表达式内部函数体在默认情况下是不能使用函数体外部的变量的, 这时候捕获列表可以起到传递外部数据的作用; 根据传递的行为不同, 捕获列表也分为几种: 值捕获/引用捕获/隐式捕获
2.value capture (值捕获)
(i). 值捕获类似于函数参数传递中的值传递, 被捕获的变量通过值copy的方式传入
(ii). 被捕获的变量在lambda表达式被创建的时候 copy, 而不是调用的时候发生 copy
(iii). 值捕获不能在lambda 函数体中修改捕获的变量值

#include <iostream>
using namespace std;

int main() {
  int a = 123;
  auto f = [a] { 
    a = 234;   //  error: cannot assign to a variable captured by copy in a non-mutable lambda
    cout << a << endl; 
  };
  a = 321;
  f(); // 输出:123
}

3.reference capture (引用捕获): 引用捕获与 pass by reference 类似, 采用引用捕获值会发生变化;

#include <iostream>
using namespace std;

int main() {
  int a = 123;
  auto f = [&a] { 
    cout << a << endl; 
  };
  a = 321;
  f(); // 输出:321
}

从值捕获改为引用捕获之后, 值可以在 lambda 函数体中发生修改

#include <iostream>
using namespace std;

int main() {
  int a = 123;
  auto f = [&a] { 
    a = 234; // 这里可以发生值的修改
    cout << a << endl; 
  };
  a = 321;
  f(); // 输出:234
}

4.implicit capture (隐式捕获): 手动写捕获列表有时候非常复杂, 这种机械的工作可以交给编译器来处理, 这是时候可以在捕获列表里面写一个 & 或者 写一个 = 向编译器生命采用引用捕获活着值捕获; 常用的可能是以下几种

[] // 空捕获列表
[name1, name2] 捕获一系列变量
[&] 引用捕获, 让编译器以引用形式捕获所有外部变量
[=] 值捕获, 让编译器以只的形式捕获所有外部变量
[=, &x] 变量x以引用的形式捕获, 其余变量以传值形式捕获;
[&, x] 变量x以值的形式捕获, 其余变量以引用捕获

举例如下:

#include <iostream>
using namespace std;

int main() {
  int a = 123;
  auto f = [&] { 
    cout << a << endl; 
  };
  f();

  int b = 234;
  auto f2 = [&a, &b] { 
    cout << a << " " << b << endl; 
  };
  f2();
  return 0;
}

Reference

1.https://www.cnblogs.com/DswCnblog/p/5629165.html. C++ 11 Lambda表达式.
2.https://changkun.de/modern-cpp/en-us/03-runtime/#Basics. Modern C++ Tutorial.


转载请注明来源, from goldandrabbit.github.io

💰

×

Help us with donation