[C++ 11札记]: std::bind
2018-03-06 15:44
274 查看
在上一篇文章中,我们提到可调用对象(callable object),其中一种就是std::bind表达式。在这篇文章中,我们来谈谈std::bind表达式。
关于std::bind的定义如下:
关于其解释可以参看:http://en.cppreference.com/w/cpp/utility/functional/bind
看上去不好理解,咱们还是以一个简单的例子来进行说明,毕竟一个例子胜过千言万语。比如有如下函数实现两个整数相加:
假如现在我们要实现某个整数加上6的函数功能,除了写一个类似的函数:
之外,我们还可以复用上面的add函数:
简单说,bind就是一个函数包装器(function wrapper),在一个通用化函数的基础上,固定一个或多个输入参数,包装成一个更加简化的函数。其好处有:
代码复用。上面的例子过于简单,可能没有表现出这个好处。但我们可以想象一下加入上面的add函数实现了很复杂的逻辑,通过copy代码的方式实现类似功能,极其容易引入bug。
易于维护,这其实也是代码复用带来的好处,代码逻辑写在一处比分散在多处更容易维护。
如果说这两点好处还不足以说服我们使用std::bind,那接下来我们要探讨的用法才是std::bind的最大用途。
在上一篇文章中,我们曾提过对象的成员函数无法与函数指针相容,主要原因在于类的成员函数都包含有一个隐含的this参数。比如:
其中的setID成员函数经过编译器的处理,等价于:
调用代码
经过编译器处理,成为:
这一切都是编译器在处理,对于实现者和调用者并不需要关心这些细节。回想之前的std::bind,我们是否可以将指针绑定到成员函数而包装成另一个函数呢?
在上述代码中,我们将Foo的成员函数包装成了
这样的类型,从而可以用在回调等场景。
当然,在实际项目的代码中,还有很多bind的用途,比如chromium项目中就有大量的bind和callback,虽然里面并不是使用的std::bind,而是使用自己定义的base::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),在一个通用化函数的基础上,固定一个或多个输入参数,包装成一个更加简化的函数。其好处有:
代码复用。上面的例子过于简单,可能没有表现出这个好处。但我们可以想象一下加入上面的add函数实现了很复杂的逻辑,通过copy代码的方式实现类似功能,极其容易引入bug。
易于维护,这其实也是代码复用带来的好处,代码逻辑写在一处比分散在多处更容易维护。
如果说这两点好处还不足以说服我们使用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,但在原理上是差不多的。
相关文章推荐
- C++ 11 std::function std::bind使用
- C++ 11 std::function std::bind使用
- C++ 11 笔记 (四) : std::bind
- C++ 11 std::function std::bind使用
- c++ 11 移动语义、std::move 左值、右值、将亡值、纯右值、右值引用
- 【C++ STL学习与应用总结】22: 函数组合之1:如何使用std::bind (since C++11)
- C++ 11 Lambda表达式、auto、function、bind、final、override
- C++ 11 左值,右值,左值引用,右值引用,std::move, std::foward
- C++ 11 笔记 (五) : std::thread
- C++ 11 bind
- C++中std::tr1::function和bind 组件的使用 和 以boost::function和boost:bind取代虚函数
- c++中的std::bind与std::function
- C++ 11: function,bind和lambda表达式
- c++ std::bind用法小结。
- 现代C++的回调技术--使用std::bind和std::function
- c++ auto tuple decltype std::bind
- C++中std::tr1::function和bind 组件的使用
- C++中的仿函数,std::function和bind()的用法
- 【原】C++ 11右值引用 std::move的作用
- C++中std::tr1::function和bind 组件的使用