Lambda表达式、std::function和std::bind学习笔记

MirrorYuChen
MirrorYuChen
发布于 2025-01-16 / 10 阅读
0
0

Lambda表达式、std::function和std::bind学习笔记

Lambda表达式、std::function和std::bind学习笔记

1.Lambda表达式

1.1 Lambda表达式语法说明

​ Lambda表达式是一种匿名函数对象,其语法形式为:

auto func = [capture](parameters) -> return_type { 
  func_body;
};
  • (1) func:Lambda表达式别名;
  • (2) capture:捕获列表,用于捕获外部作用域的变量。捕获方式说明如下:
符号 说明
[] 不捕获任何变量
[&] 按引用方式捕获作用域外部所有变量,并在函数内使用,可以更改外部变量
[=] 按拷贝方式捕获作用域外部所有变量,并在函数内使用,不可以更改外部变量,可以用mutable选项,使得函数内部可以更改外部变量
[value] 按值拷贝方式捕获 value变量,不可以更改 value
[&value] 按值引用方式捕获value变量,可以更改value值
[this] 捕获当前类的this指针,让lambda表达式拥有当前类成员函数同样访问权限,如果以使用&或=,默认添加此项
  • (3) parameters:参数列表,与普通函数的参数列表类似,可以为空;
  • (4) return_type:返回类型,可以省略,此时编译器会根据Lambda表达式的返回语句自动推导返回类型;
  • (5) func_body:具体函数实现,包含了具体的执行逻辑;

1.2 Lambda表达式示例

#include <iostream>

int main(int argc, char *argv[]) {
  auto AddOne = [](int a) -> int { return a + 1; };
  auto AddTwo = [](int a) -> int { return a + 2; };

  std::cout << AddOne(1) << " " << AddTwo(2) << std::endl;

  {
    int a = 10, b = 20;
    auto f = [](int i) { return i; };
    auto f1 = [=]() mutable { return a++; };
    auto f2 = [&] {return a++; };
    auto f3 = [=] {return a; }; 
    auto f4 = [a, &b] {return a + (b++); }; 
    auto f5 = [=, &b] {return a + (b++); };
    auto ans2 = f2(); 
    auto ans3 = f3();
    auto ans4 = f4();
    auto ans5 = f5();
    std::cout << "a = " << a << " b = " << b << std::endl;
    std::cout << "ans2: " << ans2 << " ans3: " << ans3 << " ans4: " << ans4 << " ans5: " << ans5 << std::endl;
  }

  return 0;
}

2.std::function

2.1 std::function语法介绍

​ std::function是一种泛型函数封装器,定义在 <functional>头文件中,它可以存储、复制和调用任何可调用对象,如,普通函数、Lambda表达式、函数对象和函数指针等。其语法形式为:

std::function<return_type(parameters)> func;
  • (1) return_type:函数返回类型;
  • (2) parameters:参数列表,与普通函数的参数列表类似,可以为空;
  • (3) func:函数别名;

2.2 std::function示例

#include <iostream>
#include <functional>

// 定义一个普通函数
int add(int a, int b) {
  return a + b;
}

// 定义一个函数对象类
class Multiplier {
public:
  int operator()(int a, int b) const {
    return a * b;
  }
};

class Person {
public:
  std::string name;
  int age;

  Person(std::string name, int age) : name(name), age(age) {}

  // 成员函数
  void printInfo() const {
    std::cout << "Name: " << name << ", Age: " << age << std::endl;
  }
};


int main() {
  {
    // 使用std::function封装普通函数
    std::function<int(int, int)> func = add;

    // 调用封装的函数
    int result = func(3, 5);
    std::cout << "Result: " << result << std::endl;  // 输出:Result: 8
  }
  
  {
    // 定义一个Lambda表达式
    auto lambda = [](int x, int y) { return x * y; };

    // 使用std::function封装Lambda表达式
    std::function<int(int, int)> func = lambda;

    // 调用封装的Lambda表达式
    int result = func(4, 6);
    std::cout << "Result: " << result << std::endl;  // 输出:Result: 24
  }
  
  {
    // 创建函数对象实例
    Multiplier multiplier;

    // 使用std::function封装函数对象
    std::function<int(int, int)> func = multiplier;

    // 调用封装的函数对象
    int result = func(7, 8);
    std::cout << "Result: " << result << std::endl;  // 输出:Result: 56
  }
  
  {
    // 创建Person对象
    Person person("Alice", 30);

    // 使用std::function封装成员函数,需要绑定对象
    std::function<void()> func = std::bind(&Person::printInfo, &person);

    // 调用封装的成员函数
    func();  // 输出:Name: Alice, Age: 30

    // 也可以使用Lambda表达式来封装成员函数调用
    std::function<void()> func2 = [&person]() { person.printInfo(); };
    func2();  // 输出:Name: Alice, Age: 30
  }

  return 0;
}

​ ​ 当需要对调用对象参数进行绑定、调整或预设时,可以结合 std::bind来灵活地生成新的可调用对象,以满足复杂的函数调用需求。

3.std::bind

3.1 std::bind语法介绍

​ std::bind是一个函数绑定器,它可以将一个可调用对象和其部分参数或全部参数绑定在一起,生成一个新的可调用对象,绑定后的参数在调用时将自动传递给原可调用对象。其语法形式为:

std::bind(可调用对象,参数1, 参数2, ...);

​ 传参指定需要通过 std::placeholders来进行指定,std::placeholders::_1表示第一个传参,std::placeholders::_2表示第二个参数,...。

3.2 std::bind示例

#include <iostream>
#include <functional>

int main(int argc, char *argv[]) {
  {
    auto lambda = [](int x, int y) { return x + y; };
    auto bind_lambda = std::bind(lambda, 2, std::placeholders::_1);

    std::function<int(int)> f = bind_lambda;
    std::cout << f(5) << std::endl; // output: 3
  }
  return 0;
}

​  传递给lambda函数的第一个参数为2,传递给 bind_lambda的第一个函数作为 lambda函数的第二个参数 bind_lambda函数相当于是对第一个参数默认值为2的 lambda函数地调用。 这不同于函数参数设置默认值,函数参数默认值设置需要从右到左依次设置,std::bind相较于函数参数默认值而言,更加自由和灵活

4.参考资料


评论