#include <functional>
是 C++ 标准库中的一个头文件,主要用于提供与函数对象、函数指针和函数适配器相关的功能
一:定义方式
1. 定义和使用 std::function 和 Lambda 表达式
2:使用 std::bind
你可以使用 std::bind 来绑定函数参数,并创建新的可调用对象。
补充1:std::bind
是 C++11 引入的一个函数适配器,可以将函数及其参数绑定在一起,生成一个新的可调用对象。它可以用于简化函数调用,特别是在需要部分应用或延迟调用的情况下。
相比直接调用封装到 std::function
中的好处在于可以提供更大的灵活性,尤其是在需要动态传递不同可调用对象的场景。以下是一些常见的实践应用示例,展示了封装的优势。
#include <iostream>
#include <functional>void Product(int x = 10) {std::cout << "Shuyuan: " << x << std::endl;
}int main() {// 使用 std::bind 绑定参数auto f1 = std::bind(Product, 5); // 绑定参数 5auto f2 = std::bind(Product); // 使用默认参数f1(); // 输出: Shuyuan: 5f2(); // 输出: Shuyuan: 10// 可以使用 std::placeholders 来创建更复杂的绑定int val = 20;auto f3 = std::bind(Product, std::placeholders::_1); // 占位符f3(val); // 输出: Shuyuan: 20return 0;
}
补充2:函数适配器是用于调整和转换函数接口的一种工具,使其能够与特定的调用约定或上下文兼容。在 C++ 中,函数适配器通常通过标准库中的 std::bind
、std::function
和 std::mem_fn
等实现。
常见的函数适配器
-
std::bind
:允许你固定某些参数,从而创建一个新的可调用对象。例如,将函数与某些参数绑定在一起,以便稍后调用。 -
std::function
:提供了一种类型安全的方式来存储任何可调用对象(函数指针、Lambda、函数对象等)。它允许你将不同类型的函数统一处理。 -
std::mem_fn
:用于将类成员函数转换为可调用对象,方便在 STL 算法中使用。
示例
#include <iostream>
#include <functional>void PrintSum(int a, int b) {std::cout << "Sum: " << a + b << std::endl;
}int main() {// 适配器,将第二个参数固定为 10auto boundFunction = std::bind(PrintSum, std::placeholders::_1, 10);boundFunction(5); // 输出: Sum: 15boundFunction(20); // 输出: Sum: 30return 0;
}
二:适用场景
1. 回调机制
在某些情况下,你可能需要将函数作为参数传递给其他函数,比如回调函数。通过使用 std::function
,你可以很方便地传递不同的行为。
#include <iostream>
#include <functional>
#include <vector>// 一个接受回调的函数
void processValues(const std::vector<int>& values, std::function<void(int)> callback) {for (int value : values) {callback(value);}
}void myFunction(int x) {std::cout << "Processing value: " << x << std::endl;
}int main() {std::vector<int> values = {1, 2, 3, 4, 5};// 将 myFunction 作为回调传入processValues(values, myFunction);// 也可以传入 Lambda 表达式processValues(values, [](int x) {std::cout << "Lambda processing: " << x * 2 << std::endl;});return 0;
}
2. 存储不同类型的可调用对象
#include <iostream>
#include <functional>
#include <vector>int add(int a, int b) {return a + b;
}int multiply(int a, int b) {return a * b;
}int main() {std::vector<std::function<int(int, int)>> operations;operations.push_back(add);operations.push_back(multiply);int x = 5, y = 10;for (const auto& op : operations) {std::cout << "Result: " << op(x, y) << std::endl;}return 0;
}
3. 延迟执行和动态调度
#include <iostream>
#include <functional>
#include <queue>int main() {std::queue<std::function<void()>> tasks;// 将任务加入队列tasks.push([]() { std::cout << "Task 1 executed." << std::endl; });tasks.push([]() { std::cout << "Task 2 executed." << std::endl; });// 执行所有任务while (!tasks.empty()) {tasks.front()(); // 调用队列中的第一个任务tasks.pop();}return 0;
}
三:其他方法达到类似效果
1. 使用函数指针
#include <iostream>// 定义一个接受函数指针作为参数的函数
void process(int a, void (*func)(int)) {func(a);
}// 定义一个普通函数
void myFunction(int x) {std::cout << "Value: " << x << std::endl;
}int main() {process(10, myFunction); // 输出: Value: 10return 0;
}
2. 使用模板
#include <iostream>// 定义一个接受任意可调用对象的函数
template <typename Func>
void process(int a, Func func) {func(a);
}int main() {// 使用 Lambda 表达式process(40, [](int x) {std::cout << "Lambda value: " << x << std::endl;});// 使用普通函数process(50, myFunction); // myFunction 可以直接传入return 0;
}
四:总结
std::function
定义:std::function<返回类型(参数类型...)>
- 可以使用普通函数、Lambda 表达式、函数对象等。
- 可以绑定参数,通过
std::bind
创建新的可调用对象。