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
相较于函数参数默认值而言,更加自由和灵活