一、lambda比std::bind可读性更高
lambda与正常写一个函数其实没有什么区别,但是std::bind的传入参数是理科调用的
auto setSoundL=[](int x) { setAlarm(steady_clock::now());};
// auto setSoundB=std::bind(setAlarm,steady_clock::now(),_1); //因为是立刻执行,所以需要更改写法
auto setSoundB=std::bind(setAlarm,std::bind(steady_clock::now()),_1);
二、当存在函数重载时std::bind也会存在问题
void func(int a, int b, int c);
void func(int a, int b);auto funcL=[](int b){func(5,b,10);}
auto funcB=std::bind(fun, 5, std::placeholders::_1, 10); //报错
//正确写法
using fun3ParamType=void(*)(int a,int b, int c);
auto funB=std::bind(static_cast<fun3ParamType>(func),5, std::placeholders::_1, 10);
三、功能稍微复杂的情况
auto betweenL=[lowVal, highVal](const auto& val){return lowVal<=val && highVal>=val};auto betweenB=std::bind(std::logic_and<>(),std::bind(std::less_equal<>()),lowVal,_1),std::bind(std::less_equal<>()),_1,highVal));
四、合理使用std::bind
- C++11不提供移动捕获,可以使用lambda与bind相结合
- C++11中.bind对象上的函数调用运算符使用完美转发,可接收任意参数,lambda不行
在 C++11 中,Lambda 表达式的参数列表是固定的,不能直接支持完美转发。但是从 C++14 开始,Lambda 表达式可以通过 auto&& 类型的参数实现完美的参数转发。
C++11 Lambda 的局限性
#include <iostream> #include <utility> // for std::forward// C++11 Lambda 无法直接支持完美转发 auto lambda_cxx11 = [](int x) {std::cout << "C++11 Lambda: " << x << '\n'; };int main() {int a = 42;lambda_cxx11(a); // 工作正常,但不支持完美转发// lambda_cxx11(std::move(a)); // 编译错误:lambda_cxx11 期望的是 lvalue 引用return 0; }
在这个 C++11 的例子中,Lambda 表达式只能接受特定类型的参数(这里是 int),并且不能根据调用时提供的参数类型进行调整。如果尝试传递一个右值(如 std::move(a)),就会导致编译错误,因为 Lambda 的参数列表是固定的,只接受左值引用。
C++14 Lambda 改进后的完美转发
#include <iostream> #include <utility> // for std::forward// C++14 Lambda 可以使用 auto&& 实现完美转发 auto lambda_cxx14 = [](auto&& arg) {// 使用 std::forward 将 arg 按其原始值类别转发std::cout << "C++14 Lambda: " << std::forward<decltype(arg)>(arg) << '\n'; };int main() {int a = 42;lambda_cxx14(a); // 正常工作,按 lvalue 引用转发lambda_cxx14(std::move(a)); // 也正常工作,按 rvalue 引用转发return 0; }
在这个 C++14 的例子中,Lambda 表达式使用了 auto&& 作为参数类型,这使得它可以接受任何类型的参数,并且通过 std::forward 实现了完美转发。这意味着无论你传递的是左值还是右值,Lambda 都能正确地处理它们,就像 std::bind 一样。
使用
std::bind
来创建一个绑定对象,该对象将这些参数完美转发给目标函数。#include <iostream> #include <functional> #include <utility> // for std::forward// 定义一个可变参数模板函数,用于打印所有传入的参数 template<typename... Args> void print(Args&&... args) {(std::cout << ... << std::forward<Args>(args)); // C++17 折叠表达式std::cout << '\n'; }int main() {// 使用 std::bind 创建一个绑定对象,它可以接受任意参数auto bound_print = std::bind(&print<int, double, const char*>, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);// 调用绑定对象,它会将参数完美转发给 print 函数int x = 42;double y = 3.14;const char* z = "Hello";bound_print(x, y, z); // 输出: 423.14Hello// 另一种方式是直接使用占位符,这样可以传递任意数量和类型的参数auto bound_print_any = std::bind(&print<std::string, int>, std::placeholders::_1, std::placeholders::_2);bound_print_any("World", 100); // 输出: World100// 或者完全不指定类型,让编译器推导auto bound_print_all = std::bind(print, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);bound_print_all(10, 20.5, "Test"); // 输出: 1020.5Testreturn 0; }
- C++14之后均可使用lambda表达式