• C++11 std::bind简要介绍


    note

    • 更多用法,请参考: cppreference
    • 用的少,容易忘。

    我的理解

    • 类似延迟计算。 比如,回调函数,将回调函数传入后,回调函数不一定马上被调用。
    • 它是一个模板类,调用后将生成一个新的调用对象A。调用该对象A与调用原函数是等价的。

    声明

    截至目前,它的声明如下

    需要包含头文件

    复制#include <functional>
    

    一个例子

    代码

    下面的print函数负责输出参数的值, 通过使用std::bind, 生成一个新的对象 func, 此时, func(a, b, c);print(a, b, c);**的调用结果是等价的。

    复制#include <functional>
    
    void print(int a, int b, int c)
    {
    	std::cout << "a = " << a << ", b=" << b << ", c=" << c << "\n\n";
    }
    
    int main(int argc, char* argv[], char* env[])
    {
    	auto func = std::bind(print, std::placeholders::_2, 2, std::placeholders::_1);
    
    	func(3, 4);
            
            return 0;
    }
    

    std::placeholders 说明

    std::placeholders::_2std::placeholders::_1表示参数的顺序,比如, 上面的代码示例中, 3是func的第一个参数,但是,func在声明时,指定了第一个参数的位置,放在了最后。 所以,上面的代码输出结果: a=4, b=2, c=3

    注意

    • std::bind的函数参数默认使用的是拷贝, 如果需要使用引用,则需要配合std::ref
    • 下面一个例子,帮助理解。
      print2函数负责输出参数的值,且参数都是引用, print2函数内完成对参数的自增
    复制#include <functional>
    
    void print2(int &a, int &b)
    {
    	std::cout << "函数调用:a=" << a << ", b=" << b << "\n";
    	++a;
    	++b;
    }
    
    int main(int argc, char* argv[], char* env[])
    {
    
    	int a = 1;
    	int b = 2;
    
    	auto func2 = std::bind(print2, a, std::ref(b));
    
    	std::cout << "调用前,a=" << a << ", b=" << b << "\n";
    	func2();
    	std::cout << "调用后,a=" << a << ", b=" << b << "\n";
    
            return 0;
    }
    

    调用时,尽管都采用了传入引用的方式,但略有不同。参数a使用的是传统的方式,参数b采用的是 std::ref的方式。 观察输出结果

    可以看到,std::bind的参数是以 拷贝的方式,使用 std::ref 的方式可以实现参数在std::bind的引用。

    官方的例子

    复制#include <random>
    #include <iostream>
    #include <memory>
    #include <functional>
     
    void f(int n1, int n2, int n3, const int& n4, int n5)
    {
        std::cout << n1 << ' ' << n2 << ' ' << n3 << ' ' << n4 << ' ' << n5 << '\n';
    }
     
    int g(int n1)
    {
        return n1;
    }
     
    struct Foo {
        void print_sum(int n1, int n2)
        {
            std::cout << n1+n2 << '\n';
        }
        int data = 10;
    };
     
    int main()
    {
        using namespace std::placeholders;  // for _1, _2, _3...
     
        // demonstrates argument reordering and pass-by-reference
        int n = 7;
        // (_1 and _2 are from std::placeholders, and represent future
        // arguments that will be passed to f1)
        auto f1 = std::bind(f, _2, 42, _1, std::cref(n), n);
        n = 10;
        f1(1, 2, 1001); // 1 is bound by _1, 2 is bound by _2, 1001 is unused
                        // makes a call to f(2, 42, 1, n, 7)
     
        // nested bind subexpressions share the placeholders
        auto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5);
        f2(10, 11, 12); // makes a call to f(12, g(12), 12, 4, 5);
     
        // common use case: binding a RNG with a distribution
        std::default_random_engine e;
        std::uniform_int_distribution<> d(0, 10);
        auto rnd = std::bind(d, e); // a copy of e is stored in rnd
        for(int n=0; n<10; ++n)
            std::cout << rnd() << ' ';
        std::cout << '\n';
     
        // bind to a pointer to member function
        Foo foo;
        auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1);
        f3(5);
     
        // bind to a pointer to data member
        auto f4 = std::bind(&Foo::data, _1);
        std::cout << f4(foo) << '\n';
     
        // smart pointers can be used to call members of the referenced objects, too
        std::cout << f4(std::make_shared<Foo>(foo)) << '\n'
                  << f4(std::make_unique<Foo>(foo)) << '\n';
    }
    

    官方例子输出

    复制2 42 1 10 7
    12 12 12 4 5
    1 5 0 2 0 8 2 2 10 8
    100
    10
    10
    10
    

     

  • 相关阅读:
    C#调用Matlab程序
    一台电脑,内外网同时使用
    django 表反查
    django 反查
    登录注册
    django forms自带form表单
    django url 中name
    关于django无法加载静态css、js的情况
    django static
    django models,views,urls,settings
  • 原文地址:https://www.cnblogs.com/lzjsky/p/15921529.html
Copyright © 2020-2023  润新知