• C++11--lambda表达式--包装器--bind--1119


    1.lambda表达式

    lambda表达式书写格式:[捕捉列表] (参数列表) mutable  -> 返回值类型 { 比较的方法 }

    1. int func()
    2. {
    3. int a, b, c, d, e;
    4. a = b = c = d = e = 1;
    5. // 全部传值捕捉
    6. auto f1 = [=]() {
    7. cout << a << b << c << d << e << endl;
    8. };
    9. f1();
    10. }

     注意:lambda仅是声明,在使用的时候需要调用一下 。


     1.2 参数列表的选择

    参数名称该参数
    =作用域的全部参数
    &参数名称该参数的引用
    &作用域中的全部参数引用

    注意:

    • 可以复合使用

    [=, &a, &b]:以引用传递的方式捕捉变量a和b,值传递方式捕捉其他所有变量

    [&,a, this]:值传递方式捕捉变量a和this,引用方式捕捉其他变量

    1. // 1、生命周期(存储区域)
    2. // 2、作用域(编译器编译,用的地方能否找到)
    3. int f = 1;//全局变量可以被捕捉
    4. int func()
    5. {
    6. int a, b, c, d, e;
    7. a = b = c = d = e = 1;
    8. static int x=9;//静态变量也可以被捕捉
    9. // 全部传值捕捉
    10. auto f1 = [=](){
    11. cout << a << b << c << d << e << endl;
    12. };
    13. f1();
    14. // 混合捕捉
    15. auto f2 = [=, &a](){
    16. a++;
    17. cout << a << b << c << d << e << endl;
    18. };
    19. f2();
    20. return 0;
    21. }

    •  不能重复使用

    比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重复

    1. auto f3 = [&, a]() {
    2. //a++; 不然报错
    3. b++;
    4. c++;
    5. d++;
    6. e++;
    7. f++;
    8. x++;
    9. cout << a << b << c << d << e <
    10. };
    • lambda表达式之间不能互相赋值
    1. void (*PF)();
    2. int main()
    3. {
    4. auto f1 = []{cout << "hello world" << endl; };
    5. auto f2 = []{cout << "hello world" << endl; };
    6. // 允许使用一个lambda表达式拷贝构造一个新的副本
    7. auto f3(f2);
    8. f3();
    9. // 可以将lambda表达式赋值给相同类型的函数指针
    10. PF = f2;
    11. PF();
    12. return 0;
    13. }

     1.3lambda的本质

    实际在底层编译器对于lambda表达式的处理方式,完全就是按照函数对象(仿函数)的方式处理的,即定义了一个lambda表达式,编译器会自动生成一个类,在该类中重载了operator()。

    2.包装器

    2.1function包装器

    1. template<class F, class T>
    2. T useF(F f, T x)
    3. {
    4. static int count = 0;
    5. cout << "count:" << ++count << endl;
    6. cout << "count:" << &count << endl;
    7. return f(x);
    8. }

     发现由于F的类型不同,我们写的模板实例化了三次。如果不想出现如此多的实例化,我们需要进行一次封装。

    function<返回类型(参数类型)>名称

    //将函数名进行封装

    std::function func1 = f;

    //函数对象

    std::function func2 = Functor();

    // lamber表达式

    std::function func3 = [](const int a, const int b) {return a + b; };

     静态变量的地址一样,说明是同一个静态变量,即模板只实例化了一次。

    实例化的类型就是function

    3.bind

    是一个函数模板,可以用来修改对象,从而使其”适应“参数列表。

    调用bind的一般形式:auto newCallable = bind(callable,arg_list);

     举例如下:当我们想要和上面一样对下面的函数进行封装以使模板只实例化一次。

    1. // 使用举例
    2. #include
    3. int Plus(int a, int b)
    4. {
    5. return a + b;
    6. }
    7. int Div(int a, int b)
    8. {
    9. return a / b;
    10. }
    11. int Mul(int a, int b, double rate)
    12. {
    13. return a * b * rate;
    14. }
    15. class Sub
    16. {
    17. public:
    18. int sub(int a, int b)
    19. {
    20. return a - b;
    21. }
    22. };

    这里的问题是:Plus、Div函数有两个参数,可Mul函数和在类里面的sub函数却有三个参数。我们需要借助bind强行使sub适应我们的模板。

    1. using namespace placeholders;
    2. int main()
    3. {
    4. // 调整个数, 绑定死固定参数
    5. function<int(int, int)> funcPlus = Plus;
    6. //function funcSub = &Sub::sub;
    7. function<int(int, int)> funcSub = bind(&Sub::sub, Sub(), _1, _2);
    8. //意思是我的参数只有 _1 _2这两个位置敌营的参数 是可变的
    9. //其他是写死的 于是满足了我的模板 function
    10. function<int(int, int)> funcMul = bind(Mul, _1, _2, 1.5);
    11. //意思是第三个参数固定是1.5了
    12. //编译通过
    13. mapint(int, int)>> opFuncMap =
    14. {
    15. { "+", Plus},
    16. { "-", bind(&Sub::sub, Sub(), _1, _2)}
    17. };
    18. return 0;
    19. }

  • 相关阅读:
    【Spring】IDEA&spring-mybatis的整合----关于配置文件的整合、AOP事务处理(配置&注解)
    民安智库(第三方市场调查公司)北京汽车神秘顾客调查
    【毕业设计】stm32机器视觉的口罩佩戴检测系统 - 单片机 物联网 嵌入式
    二叉树的最近公共祖先
    HTML 实现 点击按钮切换 整张界面 && 点击按钮切换局部界面
    DigestUtils实现md5加密算法
    用mysql和java写一个简易点名器
    Ros2中Action两个节点主动双向通信
    金融机构数字化转型背景下,集中式与分布式存储选型之辨和未来之路
    仿真2. 离散事件仿真
  • 原文地址:https://blog.csdn.net/qq_68741368/article/details/127954961