std::bind

std::bind返回一个function object,可以绑定:

  1. functions;
  2. function objects;
  3. member functions, _1必须是某个object地址;
  4. data members, _1必须是某个object.

std::bind()时参数或std::placeholders出现的顺序、原函数参数的顺序、新函数参数的顺序,是怎么对应的?

  • std::bind()时参数或std::placeholders出现的顺序与原函数参数是一一对应的;
  • 新函数参数与std::bind()std::placeholders是一一对应的,即新函数的第一个参数对应于_1,新函数的第二个参数对应于_2,依此类推。

1. bind的一般使用方式

#include <functional>
#include <string>
#include <iostream>

void check(const std::string& name, int age) {
    std::cout << name << " " << age << std::endl;
}

int main()
{
    /* placeholders表示的是newcallable的参数 */

    // newcallable1的第一个参数放到_1处,第二个参数放到_2处
    auto newcallable1 = std::bind(check, std::placeholders::_1, std::placeholders::_2);
    newcallable1("yujia", 1);

    // newcallable2的第一个参数放到_1处,第二个参数放到_2处,相当于newcallable1的参数互换
    auto newcallable2 = std::bind(check, std::placeholders::_2, std::placeholders::_1);
    newcallable2(1, "yujia");

    auto newcallable3 = std::bind(check, std::placeholders::_1, 1);
    newcallable3("yujia");

    // newcallable4的第二个参数放到_2处
    // 因此即使只有一个placeholder当调用newcallable4的时候还是要提供两个参数
    // 但是调用newcallable4时提供的参数是没用的
    auto newcallable4 = std::bind(check, std::placeholders::_2, 25);
    newcallable4(123,"yujia");  // 输出:yujia 25, 而不是:yujia 123

    return 0;
}

输出:
在这里插入图片描述

1.1 bind的函数参数有引用

#include <functional>
#include <fstream>
#include <string>
#include <iostream>

std::ostream& Print(std::ostream & of, std::string& str, int i) {
    return of << str << "  " << i << std::endl;
}

using namespace std::placeholders;

int main()
{
    std::ofstream out_file("ref.txt");
    std::string str = std::string("content sample");

    // 如果out_file不用placeholder方式则需要使用std::ref,因为其不可复制
#if 0
    auto newCallable = std::bind(Print, std::ref(out_file), _1, _2);
    newCallable(str, 65);
#endif
#if 1  // 使用placeholder则没有必要使用std::ref(当然也可以使用)
    auto newCallable = std::bind(Print, _3, _1, _2);
    newCallable(str, 45, out_file);
#endif

    return 0;
}

2. std::bind和其绑定的函数之间有个中间层

#include <iostream>
#include <functional>

namespace test_ref
{
    void func(int& a, int& b, const int& c)
    {
        ++a;
        ++b;
    }
    
    auto main() -> int
    {
        std::cout << "testing ref......\n" << std::endl;

        {    
            int a = 1, b = 1, c = 1;
            func(a,b,c);
            std::cout << a << ", " << b << ", " << c << std::endl;  // 2 2 1
        }
        {
            int a = 1, b = 1, c = 1; 
            // 如果不加std::ref,则给bind传递的是copy of a,然后再将a的拷贝传给func
            auto bfunc = std::bind(func, a, std::ref(b), std::cref(c));
            bfunc();
            std::cout << a << ", " << b << ", " << c << std::endl; // 1 2 1
        }
		std::cout << "------------------------------" << std::endl;

        return 0;
    }
}

3. std::bind<int/double/class/struct>?

#pragma once

#include <iostream>
#include <functional>
#include <string>

namespace test_bind
{
    struct Foo{
        int data_;
        double divide(double n1, double n2){
            if(n2){return n1 / n2;}
            else return 0;
        }
    };

    using namespace std::placeholders;
    auto main()-> void {
        std::cout << "test_bind......." << std::endl;
       
        // 使用bind用函数代替数据成员,使用placeholder
        auto bind2mem1 = std::bind(&Foo::data_, _1);
        Foo f{20};
        std::cout << bind2mem1(f) << std::endl;
        // 使用bind用函数代替数据成员,直接绑定类对象
        auto bind2mem2 = std::bind(&Foo::data_, &f);
        std::cout << bind2mem2() << std::endl;

        std::cout << std::string(20,'-') << std::endl;

        // 使用bind绑定到函数成员
        auto bind2memfunc1 = std::bind(&Foo::divide, _2, _1, _3);
        std::cout << bind2memfunc1(15, &f, 2) << std::endl;
        auto bind2memfunc2 = std::bind(&Foo::divide, &f, _1, _2);
        std::cout << bind2memfunc2(17,2) << std::endl;

        auto bind2memfunc = std::bind<int>(&Foo::divide, &f, 19, 2);
        std::cout << bind2memfunc() << std::endl;

        std::cout << "test_bind pass\n----------------------------" << std::endl;
    }
}                                                                                                                                                                                                           

输出:

test_bind.......
20
20
--------------------
7.5
8.5
9
test_bind pass
----------------------------
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值