文章目录
- 1.std::function 开启函数式编程之路
- 2.std::bind 灵活处理函数调用和传参
- 3. std::ref 传递引用的必要包装
- 4.std::thread 标准库的多线程
- 5.std::packaged_task 封装函数为可异步调用的对象
- [待续。。。]
1.std::function 开启函数式编程之路
std::function 是 C++ 标准库中的一个模板类,用于封装可调用对象(函数、函数对象、成员函数指针等),并提供一种统一的调用接口。它的主要作用是将可调用对象抽象为一个对象,使得可以像普通对象一样进行传递、存储和调用,从而提高了 C++ 中函数的灵活性和可重用性。
代码:
#include <iostream>
#include <functional>// 函数对象示例
struct Functor {int operator()(int a, int b) const {return a + b;}
};// 普通函数示例
int add(int a, int b) {return a + b;
}// 成员函数示例
class MyClass {
public:int addMember(int &a, int b) const {return a + b;}
};int main() {// 绑定普通函数std::function<int(int, int)> func1 = add;std::cout << "func1 result: " << func1(1, 2) << std::endl;// 绑定函数对象Functor functor;std::function<int(int, int)> func2 = functor;std::cout << "func2 result: " << func2(3, 4) << std::endl;// 绑定 lambda 表达式std::function<int(int, int)> func3 = [](int a, int b) -> int { return a + b; };std::cout << "func3 result: " << func3(5, 6) << std::endl;// 绑定成员函数MyClass obj;int a = 100;std::function<int(const MyClass&, int&, int)> func4 = &MyClass::addMember;a = 1000;std::cout << "func4 result: " << func4(obj, std::ref(a), 8) << std::endl;// 使用 std::placeholders 绑定成员函数std::function<int(const MyClass&, int&, int)> func5 = std::bind(&MyClass::addMember, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);std::cout << "func5 result: " << func5(obj, a, 10) << std::endl;// 使用 std::ref 传递引用int result = 0;std::function<void(int, int)> func6 = [&result](int a, int b) { result = a + b; };func6(11, 12);std::cout << "func6 result: " << result << std::endl;return 0;
}
2.std::bind 灵活处理函数调用和传参
std::bind 是 C++ 标准库中的一个函数模板,用于将函数与其参数绑定起来,生成一个可调用对象。它的主要作用是延迟函数调用,并且可以在调用时提供部分或全部的参数。std::bind 可以用于创建函数对象、绑定成员函数、创建函数适配器等。
代码:
#include <iostream>
#include <functional>// 函数对象示例
int add(int a, int b) {return a + b;
}// 成员函数示例
class MyClass {
public:int addMember(int a, int b) {return a + b;}
};int main() {int a = 1, b = 2 ;// 绑定普通函数auto func1 = std::bind(add, std::ref(a), std::ref(b)); // std::ref 见 std::ref 对应节b = a = 111;std::cout << "func1 result: " << func1() << std::endl;// 绑定成员函数MyClass obj;auto func2 = std::bind(&MyClass::addMember, &obj, std::ref(a), std::ref(b));a=b=1;std::cout << "func2 result: " << func2() << std::endl;// 绑定成员函数并传递额外参数auto func3 = std::bind(&MyClass::addMember, &obj, std::placeholders::_1, std::placeholders::_2);std::cout << "func3 result: " << func3(a, b) << std::endl;// 绑定成员函数的成员auto func4 = std::bind(&MyClass::addMember, &obj, std::placeholders::_1, std::ref(b));b = 2;std::cout << "func4 result: " << func4(a) << std::endl;return 0;
}
3. std::ref 传递引用的必要包装
std::ref 是 C++ 标准库中的一个函数模板,用于将一个对象或者引用包装为一个 std::reference_wrapper 对象,从而使得对象可以像引用一样被传递。std::reference_wrapper 对象可以在函数传参时传递引用,而不是对象的副本,这在某些情况下可以提高程序的效率。诸如:std::bind、std::function
还是不理解的话,举例如下:std::thread 在传入参数时默认为值传递,此时,对要传递的左值使用std::ref(variable) 则可以传递引用进去。示例可见 std::thread。
代码
#include <iostream>
#include <functional>void modify(int& num) {num += 10;
}int main() {int num = 5;// 通过 std::ref 将引用包装成 std::reference_wrapperauto refNum = std::ref(num);// 通过 std::reference_wrapper 传递引用modify(refNum);// 输出修改后的值std::cout << "Modified num: " << num << std::endl;return 0;
}
4.std::thread 标准库的多线程
std::thread 是 C++ 标准库中用于创建线程的类,它提供了一种方便的方式来创建并发执行的线程。
code:
#include <iostream>
#include <thread>
#include <vector>// 线程函数
void threadFunction(int& num) {++num;std::cout << "Hello from thread! Num: " << num << std::endl;
}class Worker {
public:void operator()() const {std::cout << "Hello from worker thread!" << std::endl;}
};int main() {int Num = 1;// 创建一个线程并启动//std::thread t1(threadFunction, Num ); 编译报错//t1.join();std::thread t1_ref(threadFunction, std::ref(Num) );t1_ref.join();std::cout << "Hello from Main thread! Num: " << Num << std::endl;// 创建一个线程并启动,使用 Lambda 表达式int val = 2;std::thread t2([val](){std::cout << "Hello from thread! Value: " << val << std::endl;});// 创建一个线程并启动,使用函数对象Worker worker;std::thread t3(worker);// 等待所有线程结束t2.join();t3.join();// 创建多个线程并启动std::vector<std::thread> threads;for (int i = 0; i < 5; ++i) {threads.emplace_back([i]() {std::cout << "Hello from thread " << i << std::endl;});}// 等待所有线程结束for (auto& thread : threads) {thread.join();}// 获取硬件线程数unsigned int numThreads = std::thread::hardware_concurrency();std::cout << "Number of hardware threads: " << numThreads << std::endl;return 0;
}
5.std::packaged_task 封装函数为可异步调用的对象
std::packaged_task 是 C++ 标准库中的一个类模板,用于将函数封装为一个可调用的对象,并可以异步执行该函数。它通常与 std::future 结合使用,用于获取函数执行结果。
代码:
#include <iostream>
#include <future>
#include <thread>
#include <functional>// 任务函数
int taskFunction(int a, int b) {std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作return a + b;
}int main() {// 创建一个 packaged_task,绑定任务函数std::packaged_task<int(int, int)> task(taskFunction);// 获取与 packaged_task 关联的 futurestd::future<int> future = task.get_future();// 启动一个新线程执行任务,并传递参数std::thread t(std::move(task), 1, 2);// 等待任务执行完成并获取结果int result = future.get();// 输出结果std::cout << "Result: " << result << std::endl;// 等待线程结束t.join();// 重新设置 packaged_task 关联的任务函数std::packaged_task<int(int, int)> task2;task2.reset(); // 重置为默认构造函数创建的状态return 0;
}