[C++ 11札记]: std::bind

上一篇文章中,我们提到可调用对象(callable object),其中一种就是std::bind表达式。在这篇文章中,我们来谈谈std::bind表达式。

关于std::bind的定义如下:

template< class F, class... Args >
/*unspecified*/ bind( F&& f, Args&&... args );

template< class R, class F, class... Args >
/*unspecified*/ bind( F&& f, Args&&... args );

关于其解释可以参看:http://en.cppreference.com/w/cpp/utility/functional/bind

看上去不好理解,咱们还是以一个简单的例子来进行说明,毕竟一个例子胜过千言万语。比如有如下函数实现两个整数相加:

int add(int x, int y) {
    return x + y;    
}

假如现在我们要实现某个整数加上6的函数功能,除了写一个类似的函数:

int add1(int x) { 
        return x + 6;    
}

之外,我们还可以复用上面的add函数:

auto add1 = bind(add, placeholders::_1, 6);
cout << add1(2) << endl; // print 8

简单说,bind就是一个函数包装器(function wrapper),在一个通用化函数的基础上,固定一个或多个输入参数,包装成一个更加简化的函数。其好处有:

  1. 代码复用。上面的例子过于简单,可能没有表现出这个好处。但我们可以想象一下加入上面的add函数实现了很复杂的逻辑,通过copy代码的方式实现类似功能,极其容易引入bug。
  2. 易于维护,这其实也是代码复用带来的好处,代码逻辑写在一处比分散在多处更容易维护。

如果说这两点好处还不足以说服我们使用std::bind,那接下来我们要探讨的用法才是std::bind的最大用途。

上一篇文章中,我们曾提过对象的成员函数无法与函数指针相容,主要原因在于类的成员函数都包含有一个隐含的this参数。比如:

class Simple
{
    private:
        int m_id;

    public:
        Simple(int id)
        {
            setID(id);
        }

        void setID(int id) { m_id = id; }
        int getID() { return m_id; }
};

其中的setID成员函数经过编译器的处理,等价于:

void setID(Simple* const this, int id) { this->m_id = id; }

调用代码

simple.setID(2);

经过编译器处理,成为:

setID(&simple, 2);

这一切都是编译器在处理,对于实现者和调用者并不需要关心这些细节。回想之前的std::bind,我们是否可以将指针绑定到成员函数而包装成另一个函数呢?

#include <functional>
#include <iostream>

struct Foo {
    int value;
    void f() { std::cout << "f(" << this->value << ")\n"; }
    void g() { std::cout << "g(" << this->value << ")\n"; }
};

void apply(std::function<void()> func) {
    func();
}

int main() {
    Foo foo1{1};
    Foo foo2{2};

    apply(std::bind(&Foo::f, &foo1));
    apply(std::bind(&Foo::g, &foo2));
}

在上述代码中,我们将Foo的成员函数包装成了

std::function<void()>

这样的类型,从而可以用在回调等场景。

当然,在实际项目的代码中,还有很多bind的用途,比如chromium项目中就有大量的bind和callback,虽然里面并不是使用的std::bind,而是使用自己定义的base::bind,但在原理上是差不多的。

image

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云水木石

但行好事,莫问前程

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值