93 CPP11神器之适配器bind

std::bind是一个函数适配器,用于将可调用对象(如函数、函数指针、成员函数等)与参数预先绑定,生成新的可调用对象。它可以处理值传递、引用传递以及参数占位符,方便在不同上下文中调用。在示例中展示了如何使用std::bind与不同的可调用类型(普通函数、静态成员函数、仿函数、lambda表达式、非静态成员函数和可转换为函数指针的类)配合,统一代码风格。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

std::bind()模板函数是一个通用的函数适配器(绑定器),它用一个可调用对象及其参数,生成一个新的可调用对象,以适应模板。

包含头文件:#include

函数原型:

template< class Fx, class... Args >

function<> bind (Fx&& fx, Args&...args);

Fx:需要绑定的可调用对象(可以是前两节课介绍的那六种,也可以是function对象)。

args:绑定参数列表,可以是左值、右值和参数占位符std::placeholders::_n,如果参数不是占位符,缺省为值传递,std:: ref(参数)则为引用传递。

std::bind()返回std::function的对象。

std::bind()的本质是仿函数。

#include <iostream>
#include <functional>
using namespace std;
// bind

void show(int a, const string &b)
{
    cout << a << " " << b << endl;
}

void test()
{
    function<void(int, const string &)> f1 = show;
    function<void(int, const string &)> f2 = bind(show, placeholders::_1, placeholders::_2);
    f1(1, "A1");
    f2(2, "A2");

    function<void(const string &, int)> f3 = bind(show, placeholders::_2, placeholders::_1);
    f3("A3", 3);
    //上面代码,如果不用bind,要实现这个需求,可以把普通函数show()重载一个版本,把参数的位置调换
    //但是没有bind好用
    //实际开发中,调换位置的情况不多,最常见的是少一个参数

    function<void(const string &)> f4 = bind(show, 1, placeholders::_1);
    f4("A4");

    // 用bind()提前绑定有一个细节要注意,被绑定的参数缺省值是值传递,
    int aa = 11;
    function<void(const string &)> f5 = bind(show, aa, placeholders::_1);
    aa = 200;
    f5("A5"); //输出的是 11 A5 而不是 200 A5

    //传引用
    int aaa = 11;
    function<void(const string &)> f6 = bind(show, std::ref(aaa), placeholders::_1);
    aaa = 200;
    f6("A6"); //输出的是 200 A6 而不是 11 A6

    //如果function对象需要的参数比show更多
    function<void(int, const string &, int)> f7 = bind(show, placeholders::_1, placeholders::_2);
    f7(7, "a7", 1);
}
int main()
{
    test();
    return 0;
}
/*
1 A1
2 A2
3 A3
1 A4
11 A5
200 A6
7 a7 */

用bind()提前绑定有一个细节要注意,被绑定的参数缺省值是值传递,

#include <iostream>
#include <functional>
using namespace std;
//普通函数
void show(int a, const string &b)
{
    cout << a << b << endl;
}

//类中有静态成员函数
struct AA
{
    static void show(int a, const string &b)
    {
        cout << a << b << endl;
    }
};

//仿函数
struct BB
{
    void operator()(int a, const string &b)
    {
        cout << a << b << endl;
    }
};
//类中有普通函数
struct CC
{
    void show(int a, const string &b)
    {
        cout << a << b << endl;
    }
};

//可以被转换为普通函数指针的类
struct DD
{
    using Fun = void (*)(int, const string &);
    operator Fun()
    {
        return show; //返回普通函数show的地址
    }
};

void test()
{
    // 1 不使用包装器function
    function<void(int, const string &)> pf1 = bind(show, placeholders::_1, placeholders::_2);
    pf1(1, "a1");

    //类的静态成员函数
    function<void(int, const string &)> pf2 = bind(AA::show, placeholders::_1, placeholders::_2);
    pf2(2, "a2");

    //仿函数
    BB bb;
    function<void(int, const string &)> pf3 = bind(bb, placeholders::_1, placeholders::_2);
    pf3(3, "a3");

    //创建lambda对象
    auto lambfunc = [](int a, const string &b)
    {
        cout << a << b << endl;
    };
    function<void(int, const string &)> pf4 = bind(lambfunc, placeholders::_1, placeholders::_2);
    pf4(4, "a4");

    //类的非静态成员函数    这里是最大的优化
    CC cc;
    function<void(int, const string &)> pf5 = bind(&CC::show, cc, placeholders::_1, placeholders::_2);
    // function<void(int, const string &)> pf5 = bind(&CC::show, CC(), placeholders::_1, placeholders::_2);
    pf5(5, "a5");

    //可以被转换的函数指针的类
    DD dd;
    // function<void(int, const string &)> pf6 = bind(dd, placeholders::_1, placeholders::_2);
    function<void(int, const string &)> pf6 = bind(DD(), placeholders::_1, placeholders::_2);
    pf6(6, "a6");
}
int main()
{
    test();
    return 0;
}
/*
1a1
2a2
3a3
4a4
5a5
6a6 */

上面demo,通过bind适配器,把六种可调用对象的代码统一了

bind()返回的是function模板类的对象,比较长,也可以用auto

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值