START
Hi,大家好!今天我们来说一说c 中std::function、std::bind、lambda等用法,这些用法使函数调用更加方便。
unsetunsetstd::functionunsetunset
std::function
是 C 11 标准库中的一个模板类,它可以用于包装任何可调用对象(函数、函数指针、成员函数、lambda 表达式等),并提供一种统一的方式来管理和调用这些可调用对象。
下面是 std::function
的主要特点和用法:
- 函数包装器:
std::function
可以包装各种可调用对象,包括函数、函数指针、成员函数指针、lambda 表达式等。 - 类型安全:
std::function
提供了类型安全的方式来管理可调用对象,编译器会在编译时检查参数和返回值的类型是否匹配。 - 灵活性:
std::function
可以在运行时决定要调用的具体函数或者函数对象,使得代码更加灵活。 - 可复制性:
std::function
对象是可复制的,可以像普通对象一样进行复制和赋值操作。
下面是 std::function
的基本用法示例:
#include <iostream>
#include <functional>
// 函数对象类
class MyFunctionObject {
public:
int operator()(int a, int b) const {
return a b;
}
};
// 普通函数
int add(int a, int b) {
return a b;
}
int main() {
// 使用函数对象
MyFunctionObject myObject;
std::function<int(int, int)> func1 = myObject;
// 使用普通函数
std::function<int(int, int)> func2 = add;
// 使用 lambda 表达式
std::function<int(int, int)> func3 = [](int a, int b) { return a b; };
std::cout << "Result 1: " << func1(1, 2) << std::endl;
std::cout << "Result 2: " << func2(3, 4) << std::endl;
std::cout << "Result 3: " << func3(5, 6) << std::endl;
return 0;
}
在这个示例中,我们演示了如何使用 std::function
包装函数对象、普通函数和 lambda 表达式,并通过调用 std::function
对象来执行相应的操作。
unsetunsetstd::bindunsetunset
std::bind
是 C 11 标准库中的一个函数模板,用于创建一个可调用对象(函数对象或函数指针),并绑定到指定的参数。它可以用于延迟函数调用、部分应用函数、改变函数参数顺序等场景。
下面是 std::bind
的主要特点和用法:
- 延迟函数调用:
std::bind
允许我们在创建可调用对象时不立即调用函数,而是将函数对象和参数绑定起来,以便在稍后的时间点进行调用。 - 部分应用函数:
std::bind
允许我们在创建可调用对象时只绑定部分参数,剩余的参数可以在稍后的调用中提供,从而实现函数的部分应用。 - 改变函数参数顺序:
std::bind
允许我们改变函数的参数顺序,即将函数的某些参数按照指定的顺序重新排列。 - 支持占位符:
std::bind
支持占位符(std::placeholders::_1
、std::placeholders::_2
等),用于指示在调用时提供的参数的位置。
下面是 std::bind
的基本用法示例:
#include <iostream>
#include <functional>
// 函数对象类
class MyFunctionObject {
public:
int operator()(int a, int b, int c) const {
return a b c;
}
};
int main() {
MyFunctionObject myObject;
// 绑定函数对象和参数
auto func1 = std::bind(myObject, 1, 2, 3);
// 部分应用函数
auto func2 = std::bind(myObject, std::placeholders::_1, 2, std::placeholders::_2);
std::cout << "Result 1: " << func1() << std::endl; // 输出:6
std::cout << "Result 2: " << func2(10, 20) << std::endl; // 输出:32
return 0;
}
在这个示例中,我们使用 std::bind
将函数对象 myObject
绑定到参数,并创建了两个可调用对象 func1
和 func2
。func1
绑定了完整的参数,而 func2
则只绑定了部分参数,剩余的参数在调用时提供。
unsetunsetlambdaunsetunset
Lambda 表达式是 C 11 引入的一种匿名函数语法,它可以方便地创建临时函数对象,用于在函数调用时作为参数传递或者作为局部函数使用。Lambda 表达式可以捕获外部变量,并具有与普通函数相似的语法结构。
Lambda 表达式的一般语法形式如下:
代码语言:javascript复制[capture](parameters) -> return_type { body }
其中:
capture
:捕获列表,用于指定 Lambda 表达式访问的外部变量。parameters
:参数列表,与普通函数的参数列表类似。return_type
:返回类型,可以省略,编译器会自动推导返回类型。body
:Lambda 函数体,与普通函数的函数体类似。
下面是一些 Lambda 表达式的常见用法:
无捕获、无参数、无返回值的 Lambda 表达式:
代码语言:javascript复制[]() { std::cout << "Hello, Lambda!" << std::endl; }
有捕获、有参数、有返回值的 Lambda 表达式:
代码语言:javascript复制int x = 10;
auto func = [x](int y) -> int { return x y; };
Lambda 表达式作为函数对象传递:
代码语言:javascript复制std::vector<int> nums = {1, 2, 3, 4, 5};
int total = 0;
std::for_each(nums.begin(), nums.end(), [&total](int x) { total = x; });
Lambda 表达式作为排序函数的比较器:
代码语言:javascript复制std::vector<int> nums = {5, 3, 1, 4, 2};
std::sort(nums.begin(), nums.end(), [](int a, int b) { return a < b; });
Lambda 表达式捕获外部变量:
代码语言:javascript复制int x = 10;
auto func = [x](int y) { return x y; };
Lambda 表达式的参数列表和返回类型的自动推导:
代码语言:javascript复制auto func = [](int x, int y) { return x y; };
Lambda 表达式的默认捕获方式:
代码语言:javascript复制int x = 10;
auto func = [=](int y) { return x y; }; // 默认以值方式捕获所有外部变量
Lambda 表达式的可变捕获:
代码语言:javascript复制int x = 10;
auto func = [x]() mutable { x ; }; // 使用 mutable 关键字使捕获的变量可变
以上是 Lambda 表达式的一些常见用法示例,它们可以帮助简化代码,提高代码的可读性和可维护性。