当前位置: 首页 > article >正文

条款34 考虑lambda而非std::bind

一、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.5Test
    
        return 0;
    }
  • C++14之后均可使用lambda表达式

http://www.kler.cn/a/447550.html

相关文章:

  • Docker_常用命令详解
  • flink实现复杂kafka数据读取
  • 从0-1开发一个Vue3前端系统页面-9.博客页面布局
  • 【人工智能数学基础】——深入详解贝叶斯理论:掌握贝叶斯定理及其在分类和预测中的应用
  • 国内主流数据库介绍及技术分享
  • 使用 MyBatis-Plus Wrapper 构建自定义 SQL 查询
  • JS中的innerHTML,innerText,value的区别
  • STM32-笔记5-按键点灯(中断方法)
  • java线程
  • Unity实用技能-协作规范总结
  • MySQL数据库下载及安装教程
  • linux美化命令行
  • 文件I/O操作:C语言
  • 纯血鸿蒙APP实战开发——Text实现部分文本高亮和超链接样式
  • el-tabs标签过多
  • TCP与UDP的端口连通性
  • Ubuntu22.04安装CH340/CH341驱动
  • Python自动化测试图片比对算法
  • 电商项目-网站首页高可用(二)
  • 常用数据库类型介绍
  • 从 Vue 迈向 React:平滑过渡与关键注意点全解析
  • 翻转(蓝桥杯2023大学C组试题E)
  • 力扣274. H 指数
  • 【八大排序(二)】希尔排序
  • 5_HTML5 SVG (1) --[HTML5 API 学习之旅]
  • 深入理解贪心算法:核心概念与实践